「F#をまねる」をまねる
F# の |> 演算子がかっこよいので、Haskell で作ってみた。
infixl 0 |> (|>) :: a -> (a -> b) -> b a |> f = f a以下のようにシェルのパイプのような感じで使う。
foo :: String foo = [1..100] |> map (*2) |> filter (\x -> x `mod` 6 == 0) |> sum |> showhttp://d.hatena.ne.jp/kazu-yamamoto/20110218/1297992233
Schemeでマクロを活用して真似てみる.
(define-syntax >> (syntax-rules () ((_ value) value) ((_ value (proc args ...) expr ...) (>> ((cut proc args ... <...>) value) expr ...)))) (define-syntax >>* (syntax-rules () ((_ value) value) ((_ value (proc args ...) expr ...) (>>* (call-with-values (lambda () value) (cut proc args ... <...>)) expr ...))))
名前は適当,>>*は多値対応版だけどGaucheでは遅くなってしまった.気にする所じゃなさそうだけど.
使い方は
(>> (iota 100) (filter odd?) (map (pa$ * 2)) (fold + 0)) ; => 5000 (>> (iota 100) (filter odd?) (map (pa$ * 2)) (take <> 10)) ; => (2 6 10 14 18 22 26 30 34 38) (>>* (values 7 2) (quotient&remainder) (+)) ; => 4
(追記6:46)
@dico_leque さんにGaucheではcall-with-valuesよりreceiveの方が少し速いと教わったので書いてみた.速くなった.Gaucheではreceiveの方がプリミティブでcall-with-valueはただの手続きとのこと.
(define-syntax >>+ (syntax-rules () ((_ value) value) ((_ value (proc args ...) expr ...) (receive vars value (>>+ (apply (cut proc args ... <...>) vars) expr ...)))))
名前はますます適当である.
Gauche 0.9.2 で計測.コード適当だけど受け渡し部分を計りたいんだからこれでいいよね?
;(time (dotimes (_ 100000) (>> 1 (+ 2) (+ 3) (+ 4) (+ 5) (+ 6) (+ 7)))) ; real 0.231 ; user 0.220 ; sys 0.000 ;(time (dotimes (_ 100000) (>>* 1 (+ 2) (+ 3) (+ 4) (+ 5) (+ 6) (+ 7)))) ; real 0.395 ; user 0.380 ; sys 0.010 ;(time (dotimes (_ 100000) (>>+ 1 (+ 2) (+ 3) (+ 4) (+ 5) (+ 6) (+ 7)))) ; real 0.341 ; user 0.330 ; sys 0.000
(追記19:53)
(define-syntax $> (syntax-rules (=>) ((_ value) value) ((_ value => proc expr ...) ($> (proc value) expr ...)) ((_ value (proc args ...) expr ...) ($> ((cut proc args ... <...>) value) expr ...))))
($> 3 => (^x (+ x x)) (- <> 1)) ; => 5