From: Masahiro Sakai (=?iso-2022-jp?B?GyRCPHIwZkAvTTUbKEI=?=) Date: 2002-05-14T03:51:33+09:00 Subject: [ruby-list:35106] Re: かりー化 酒井です。 From: Shin-ichiro HARA Subject: [ruby-list:35092] Re: かりー化 Date: Mon, 13 May 2002 19:53:25 +0900 > 情報満載なので、いつも「日々の流転」楽しみにしております。_o_ うおぉ、そんな風に思われていたとは光栄です。 > 酒井さんの「メソッドのカリー化」のコードは載せないんですか? では載せましょう。 ただ、こっちは ・ブロックの事を考慮してない ・UnboundMethodを使ってるので継承と相性が悪そうだ といった理由で自分ではイマイチだと思っています。 require 'thread' class Module CURRYING_METHOD_TABLE_ = Array.new CURRYING_METHOD_TABLE_MUTEX_ = Mutex.new def currying(name, arity=nil) m = instance_method(name) if m.arity == 0 return elsif m.arity > 0 arity = m.arity else arity ||= (-m.arity)-1 end tbl_idx = nil CURRYING_METHOD_TABLE_MUTEX_.synchronize{ tbl_idx = CURRYING_METHOD_TABLE_.size CURRYING_METHOD_TABLE_ << m } module_eval %Q[ def #{name.to_s}(*args1) proc = lambda{|*args| if args.size >= #{arity} Module::CURRYING_METHOD_TABLE_[#{tbl_idx}].bind(self).call(*args) else lambda{|*a| proc.call(*(args + a))} end } proc.call(*args1) end ] end end class < Hello, Ruby! end > そういえば「カリー化」の定義を言わないと。 すっかり忘れていました。(^^;; 僕は正確な定義は良く知らないのですが、原さんが下に書いているように X×Y→Z のような多引数の関数を X→(Y→Z) というような _関数を返り値とする_1引数の関数に変換する事をカリー化と呼ぶらしいです。 Rubyで使う場合には、引数の数を1個に制限するよりは 一度に可変個の引数を受け取れた方が嬉しいだろうという事で、 このようなコードにしてみました。 > 多変数の関数、例えば f(x, y, z) に、対して > > F(x)(y)(z) = f(x, y, z) > > を満たすような、関数の関数の、、、関数 F を作る事をカリー化って > いうんですよね。ここではその Proc バージョンであると。 -- さかい