LoginSignup
7

More than 5 years have passed since last update.

Symbol からレシーバを後挿しできる Proc を得られるようにするとブロックなし Ruby が捗る

Last updated at Posted at 2015-01-22

ブロックなしRubyをやろうとすると関数型プログラ…うーんリストプロセッ、えーと感じ感じ

めっちゃいい話です。

ブロックを使わずに "レシーバを未定にし、メソッドの実引数のみ部分適用した Proc オブジェクトを生成" したいことが結構あります。
できないのでつらみがある。
でも Symbol に任意の引数をあらかじめ適用しておいてからレシーバを後挿し可能な Proc というものを得ることができればよさそうな気がしますね。
そんなかんじで Symbol を拡張した話をします。

そういう記事自体はすでに以前 blog に書いていた のですがタイムリーっぽい気がするので Qiita にも載せます。

class Symbol
  def call(*argv)
    case
    when block_given?
      -> obj { self.to_proc[obj, *argv, &proc] }
    when argv.size > 0
      -> obj { self.to_proc[obj, *argv] }
    else
      self.to_proc
    end
  end
end

p [[1,2,3],[2,4,6],[5,7,9]].map(&:inject.(:+))
p [[1,2,3],[2,4,6],[5,7,9]].map(&:select.(&:odd?))
p [[1,2,3],[2,4,6],[5,7,9]].map(&:slice.(1,1))

以前 gist に載せたコードから当該部分をまんま引っ張ってきただけです……。

引数の順番を入れ替える lambda でラップして、レシーバだけを未定なままにして Proc を得られるようにしてあります。

xs = (1..10)
xs.map(&:to_s.(2))

よさそうですね。

といっても見てのとおりちゃっちい作りなので使ってみるとこれだけだと不充分なこともあります。レシーバを後挿しにできるというかそれ以外のことはできないです。

前にこのコードを書きながらもう lambda driver あるよと思ったんだけど前に書いたときは自分で手を動かすことで関数型っぽいものに対する理解が深まるんじゃないかな-かなーという感じでした。
いまこうして Qiita に載せたのは単にタイムリーっぽい気がしたからという不純な動機からだったりしますが、まあでもこれくらいの短いコードから関数型っぽいものに対する理解が深まっていけばいいなーと思ってます。

追記1

続き があります。

追記2

わざわざカリー化して部分適用しなくてもよかったので直しました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7