読者です 読者をやめる 読者になる 読者になる

非衛生な syntax-rules

Scheme のハイジニック (衛生的) マクロは同名の変数が衝突することを自動的に回避するシステムを備えている。 しかし、 syntax-rules も syntax-case もパターンマッチの能力を有することから衛生的であることとパターンマッチとが混同されがちである。
そこで、 syntax-rules を非衛生にした版を書いてみた。 R6RS 処理系なら使えるはず。

(define-syntax nonhygienic-syntax-rules
  (lambda (x)
    (syntax-case x ()
      [(_ (lit ...) [(k . p) t] ...)
       (for-all identifier? #'(lit ... k ...))
       #'(lambda (x)
           (syntax-case x (lit ...)
             [(k2 . p)
              (datum->syntax #'k2 (syntax->datum #'t))] ...))])))

これを使えば syntax-rules で書けないマクロの代表例であるアナフォリックマクロも簡単に書ける。 試してみよう。

(define-syntax aif
  (nonhygienic-syntax-rules ()
    ((aif test then)
     (let ((it test)) (if it then)))))

(display (aif (member 3 '(1 2 3 4 5)) it))

syntax-rules では書けないがパターンマッチは欲しくて、かといって syntax-case をそのまま使うのも面倒というような場面というのは結構あるのではなかろうか。
Document ID: 99da5a1270d0c0ecc94d60c6ae346ddc