さて、先日書いた pattern-match-lambda
について。
少し改良してアンダーバーをプレイスホルダとして使えるようにした。
(define example (pattern-match-lambda () ((_) 'arity1) ((_ _) 'arity2) ((_ _ _) 'arity3))) (example 1 1 1) ;; ⇒ arity3
プレイスホルダの箇所はそこに何か有りさえすれば内容にかかわらずマッチし、マッチした内容を見ることも出来ない。 適当なパターン変数を書いてもよいのだが使わないということを明示できるし、無駄な比較処理などが入らないので効率もよい。 (コンパイラが充分に賢いなら差はなくなるはずだが。)
もしリテラル節にアンダーバーを記述した場合にはリテラルとしてマッチするようになり、プレイスホルダとしての機能は失われる。
(define example4 (pattern-match-lambda (_) ((_) 'underbar) ((x) x))) (example4 '_) ;; ⇒ underbar (example4 'foo) ;; ⇒ foo
この挙動は R7RS の syntax-rules
を真似したものだ。
これを機にあらためて syntax-rules
におけるアンダーバーの扱いを見ると R5RS, R6RS, R7RS でそれぞれ異っていることに気付いた。 表にまとめてみよう。
R5RS | R6RS | R7RS | |
プレイスホルダとして使える | × | ○ | ○ |
リテラル節に書いてよい | ○ | × | ○ |
地味な違いだが、地味なだけに意識されにくい。 pattern-match-lambda
の今回の改良にあたってこれが原因で R6RS では使えなくなってしまった。 syntax-rules
だけを使っていれば移植性の高いものを書けると思っていたのに、そう簡単な話でもないようだ。
Document ID: 735c6332198a48e5ea92f4977463f856