プレイスホルダ

さて、先日書いた 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