patorashのブログ

方向性はまだない

Ruby2.6の関数合成で遊んでみた

Ruby 2.6が出て2ヶ月が経過しているものの、まだ触ってなかったので新機能を調べていたら、関数合成ができるようになっていたのを知った。

techlife.cookpad.com

これを使えば多少の加工だったらmapを2周したりしなくて済むんじゃないか?と思って実験してみた。

Procを先に定義するパターン

先に定義してあるので、mapしているところは見易いしわかりやすい。けれど、やっぱり先に定義したくない。

a = -> (x) { x.upcase }
b = -> (x) { x.strip }
["abc   ", "   def", " ghi "].map(&(a >> b))
=> ["ABC", "DEF", "GHI"]

Procを定義せずにto_procを使うパターン

先に定義せずにすると、こうなる。しかし、これはこれでto_procがやかましい…。

["abc   ", "   def", " ghi "].map(&(:upcase.to_proc >> :strip.to_proc))
=> ["ABC", "DEF", "GHI"]

injectを使うパターン

配列に定義したsymbolをto_procしてinjectで合成する。カッコイイ。けれど、長い。

["abc   ", "   def", " ghi "].map(&([:upcase, :strip].map(&:to_proc).inject(&:>>)))
=> ["ABC", "DEF", "GHI"]

理想の書き方

動かないけれど、理想の書き方は…

["abc   ", "   def", " ghi "].map(&(:upcase >> :strip)) # => Not working...

みたいな感じがいいなぁと思う。

Array型をオープンクラスしてcompose関数とかを追加するのがいいのかもしれない。

class Array
  def compose
    self.map(&:to_proc).inject(&:>>)
  end
end
["abc   ", "   def", " ghi "].map(&([:upcase, :strip].compose))
=> ["ABC", "DEF", "GHI"]

やらんけど。