落ちていくRubyistのためのMethopオブジェクト
すごく技巧的なので驚きました。何だかよくわからなかったので、調べてみました。
まずコピペです。
.[](method) new(method).build (method) @method = method ->arg, obj{ obj.send(@method, arg) }.curry = Methop[:+] .map(&]) #=>["rubyist", "violinist", "novelist"]補足などして、多少書き直してみます。
.[](method) a = Methop.new(method) a.build (method) @method = method {|arg, obj| obj.send(@method, arg)}.curry end end plus = Methop[:+] p .map &plus.call() #=>["rubyist", "violinist", "novelist"]まずクラスbuild によって与えられる Proc オブジェクトが入ります。インスタンス変数 @method には、演算子 + が(ここでは Symbol として)入ります。
map 実行時に、レシーバーである Array の要素が次々に Proc オブジェクトの引数 obj に入ります。plus.call('ist') で引数 arg に "ist" が入り、Proc オブジェクトが実行されます。前に付いている & は、その Proc オブジェクトをブロックに直し、map に与えています(参照)。これでお終いです。すごいですね。
上のキモを例示しておきます。
a = ->(s, t){t + s}.curry [, ].map &a.call() #=>["rubyist", "violinist"]
こういうことのできる Ruby は本当におもしろい言語ですね。わかってみればとても美しいではないか。それにしても、ブロックという言語仕様は Matz が気に入っていると云うとおり、味のあるやつですなあ。
※追記
なお、元のコードで map() となっている括弧は、引数を括っているわけではないと思います。map は引数を取らないので。ただブロックをラップしているだけなのではないでしょうか。いや、[1, 2, 3].map({|i| i ** 2}) がエラーになるからちがうかな。どうなのでしょう。ちなみに、%w|perl, python, ruby|.map(&:upcase) の map と括弧の間に空白を入れるとエラーになるから、特殊な構文なのですかね。