Mon Mar 4 21:53:06 JST 2013

最近になってマクロ書くことを覚えた。

(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)))

って書いて、右から、というかカッコの内側を目で捕捉して、そこから外側へ 読んでいかないといけない。 カッコの外側が、ただ左に向かってるからまだいいものの、左にも右にも 広がってたりしたら絶望的だ。まあ、あんまりそういうのは無いか。 とくに例も思いつかないし。