Rubyでflip
関数合成できた。ポイントフリーができた。カリー化もある。
なら次はflipで部分適応の順序を入れかえてやりたい。
まずは下記のProc#flipを見て試す。
http://yuroyoro.hatenablog.com/entry/2012/08/10/232443
div = lambda{|x,y| x.to_f / y } div.(10,2) #=> 5.0 div.flip.(10,2) #=> 0.2
確かにできてる。でも3つ引数をとる場合、第2引数と第3引数を部分適応することはできないらしい。
やってみる。
f = ->a,b,s { s.to_s.gsub(a, b) } p f.(/oo/,"aa","foooo") #=> "faaaa" p f.flip.("aa", /oo/,"foooo") #=> "faaaa" p f.flip.curry.("aa").flip.("foooo").(/oo/) #=> "(?-mix:oo)" わけのわからん物が返ってきた。
確かに一度カリー化されたProcに対してflipしても効果がない。当然だけど…
でもあきらめちゃだめだ。
上記のアプローチはカリー化されてないものに対してのflipしかない
ならカリー化されてるものに対してのflipを書けばいい。
実装は以下
def flip ->f, x, y { f[y][x] }.curry end
このflipを使って第2引数と第3引数を先に部分適応できる形に変換してやるとこうなる
f1 = (flip << flip.(f.curry)) p f1.("aa").("foooo").(/oo/) #元の呼び出しはこう⇒ f.(/oo/,"aa","foooo") #=> "faaaa"
変換の途中経過は以下
# 第1引数と第2引数をひっくり返す p flip.(f.curry).("aa").(/oo/).("foooo") #=> "faaaa" # 元の第1引数と第3引数をひっくり返す # つまりひとつ前の第2引数と第3引数をひっくり返す p flip.(flip.(f.curry).("aa")).("foooo").(/oo/) #=> "faaaa" # 最後に関数合成をして元の第2引数を外に追いやる # ひとつ前で関数の中に埋ってる"aa"を追いやる f1 = (flip << flip.(f.curry)) p f1.("aa").("foooo").(/oo/) #元の呼び出しはこう⇒ f.(/oo/,"aa","foooo") #=> "faaaa"
カリー化されてるProcに対してもflipできた。