cond-cons
Scheme:マクロの効用のリストの構築で、cond-consというマクロが紹介されてるけど、Common Lispで欲しくなったので書いてみた。
(defmacro cond-cons (&rest clauses)
(labels ((rec (clauses)
(if clauses
(let ((clause (car clauses))
(r (rec (cdr clauses))))
`(if ,(car clause) (cons (progn ,@(cdr clause)) ,r) ,r))
nil)))
(rec clauses)))
一瞬、rが複数回評価されて、副作用があるとまずいんじゃ、とか思ったけど、考えたらifで分岐するから問題なかった。
マクロなのに末尾再帰版。すみません。大好きです末尾再帰。
(defmacro cond-cons (&rest clauses)
(labels ((rec (clauses fn)
(if clauses
(let ((clause (car clauses)))
(rec (cdr clauses)
(lambda (x)
`(if ,(car clause)
(cons (progn ,@(cdr clause)) ,(funcall fn x))
,(funcall fn x)))))
`(nreverse ,(funcall fn nil)))))
(rec clauses (lambda (x) x))))
コンパイル時にしか評価されないので、ほとんど意味がない。末尾再帰じゃないバージョンだとスタックが溢れるくらい、clausesが長いリストだったりするなら多少は意味があるだろうけど、それってどんなだよ。
Paul Grahamも同じ趣旨のことをOn Lispかどこかに書いてたように思うけど、マクロ定義のコードで頑張る意味なんてない。
ちなみに、Gaucheでは、util.listにcond-listという名前で、より高機能なものが収録されている。何でそんなことを書くかというと、以前探したときに、しばらく見付けられなかったからではない。そんなわけはない。
0 件のコメント:
コメントを投稿