最近になってマクロ書くことを覚えた。
(define-syntax for
(syntax-rules (where in)
((_ expr where i in ls) (map (lambda (i) expr) ls))
((_ expr where i in ls cnd)
(filter (lambda (i) cnd) (for expr where i in ls)))
((_ expr where i in ls cnd cnd2 ...)
(filter (lambda (i) cnd) (for expr where i in ls cnd2 ...))) ))
gosh> (for i where i in (iota 10))
(0 1 2 3 4 5 6 7 8 9)
gosh> (for (* i i) where i in (iota 10))
(0 1 4 9 16 25 36 49 64 81)
gosh> (for (* i i) where i in (iota 10) (odd? i))
(1 9 25 49 81)
whereの代わりに適当な区切り文字として;はコメント記号だし、|は括り文字だしで:使おう と思ったけどたぶんキーワード引数の為に使えないし、結構使えない記号多い。'を変数名 に使えないのが、個人的には一番痛い。何も考えず x に対して x' をlet束縛するとか、 MLだとしょっちゅうやるから。
自分はどこでも言ってるけど、F#のパイプライン演算子は本当にいいなあって思う。 手続きの順序を上からただ読めばいいから。行頭をちゃんと揃えて書けばとっても わかりやすい。S式は右から左に逆に読まないといけなくなるもんね。
(define-syntax pipe
(syntax-rules (>>)
((_ x >> f) (f x))
((_ x >> f >> g ...) (pipe (f x) >> g ...)) ))
gosh>
(pipe 10
>> iota
>> (pa$ filter odd?)
>> (pa$ map (^x (* x x))) )
(1 9 25 49 81)
普通なら
(map (^x (* x x)) (filter odd? (iota 10)))
って書いて、右から、というかカッコの内側を目で捕捉して、そこから外側へ 読んでいかないといけない。 カッコの外側が、ただ左に向かってるからまだいいものの、左にも右にも 広がってたりしたら絶望的だ。まあ、あんまりそういうのは無いか。 とくに例も思いつかないし。