F#はOCamlの拡張にも見えるけど独特の関数適用、関数合成の 演算子が面白い.
let (|>) x f = f x
let (<|) f x = f x
let (>>) f g = fun x -> g (f x)
let (<<) f g = fun x -> f (g x)
上の2つは順次パイプライン演算と呼ばれ
下の2つは順次合成演算という
入力のしやすさよりも見た目の良さを優先させている観がある.
()で括った二項演算子は中間記法を前提としていて、つまり
x |> f
と書いて f x
を表す.
(<|)
, (|>)
は左結合(<<)
は右結合(>>)
は左結合結合優先順位としては
(通常の関数適用) >> (|>) > (<<), (>>) > (<|)
左結合右結合は慣れればだいたい見た目通りに思える. 結合優先順位が若干曲者
let sq x = x * x
let add1 x = x + 1
(sq (add1 2))
これを次のように書く.
2 |> add1 |> sq
次はエラー
sq <| add1 <| 2
これは
(sq add1) 2
と解釈される.
括弧を補うならば
sq <| (add1 <| 2)
とするしかない. 左向きのパイプラインは関数合成を組み合わせるのが前提で(たぶん)
sq << add1 <| 2
とすると、
(fun x -> sq (add1 x)) 2
と解釈される.
右向きのパイプライン結合と左向きのパイプライン結合が キレイに左右対象になっていない.ちょっと嫌だ.
f,g,hという3つの関数にxという数を通す
f (g (h x))
をパイプラインで書くことを考えると
x |> h |> g |> f
これはxをhして、gして、fする、と考えたことと文章が一致 していてとてもいい.Haskellになどには(簡単に定義できる にしても)ない演算だ.
左向きのパイプラインでは
f << g << h <| x
となる.記号が左右対象にならない.