(Scheme) syntax-rulesの引数が1つのパターンは省略できる?
前からあやふやだったので確認してみた。
これでandマクロが作れるのは違和感がある。
(define-syntax myand (syntax-rules () ((_) #t) ((_ e1 e2 ...) (if (not e1) #f (myand e2 ...)))))
(_ e1 e2 ...) が引数2つ以上を表すならば、上のマクロ定義では1引数の場合に対応できないはず。でもちゃんと動いてしまう。
(myand #f) ;=> #f
衛生マクロはあまり詳しくないのだけど、これは正しい動作なのだろうか?
試した処理系は racket と gauche。どちらも通る。
追記
マクロ展開形を見ればわかることでしたね。
(myand #f)
をexpandすると
(if (not #f) #f (myand))
なんと無くそんな気はしていたんだけど、
上で書いた (_ e1 e2 ...) は引数2つ以上を表しているわけではないようです。
ここに違和感があるんだけど、そういうルールなのかな。
追記2
答えはこちら。
@mnzktw e ... というパターンはゼロ個以上の並びにマッチするんだったはずです
— 括弧を数えるな、感じろ! (@athos0220) 2014, 12月 27
(_ e1 e2 ...) は引数2つ以上、ではなく、引数1つ以上をあらわす。引数が1つだけの場合、 e2 ... の部分はまるっきり存在しないものとして式展開されるということのようです。
意味的には「引数1のケースが未定義」ではなく、「引数1つ以上のケースを定義」していると考えるのが正しい。