トップ «前の日記(2002-05-06) 最新 次の日記(2002-05-08)» 月表示 編集

日々の流転


2002-05-07 [長年日記]

λ. カリー化(?)

class Proc
  def currying(arity=nil)
    if self.arity == 0 || self.arity == 1
      return self
    elsif self.arity > 0
      arity = self.arity
    else
      arity ||= (-self.arity)-1
    end
    
    proc = lambda{|base|
      lambda{|*a|
        args = base + a
        if args.size >= arity
          call(*args)
        else
          proc.call(args)
        end
      }
    }
    
    proc.call([])
  end
end
 
if __FILE__ == $0
  add = lambda{|a,b| a+b}.currying
  succ = add[1]
  p succ[100] #=> 101
  p succ[3] #=> 4
end

【2008-02-10追記】 [ruby-dev:33676] Suggestion: Proc#curry遠藤さんが Proc#curry として同様(?)のものを提案している。 そこで言及されている Ruby, Proc#curry - 冬通りに消え行く制服ガールは、夢物語にリアルを求めない。 - subtech のコードは随分と妙なコードではあるけれど。

Tags: ruby

λ. 未踏ソフトウェア

萩野/服部研の人は誰も応募しないのかしら。とか書いてみるテスト。

Tags: tom

λ. 続 Y Combinator

http://www.itlabs.umn.edu/HyperNews/get/gopalan/courses/CSCI8980-fall-2001/classwork/2.htmlを見ると、MLやHaskellでもY Combinatorを一応使えるのか。でもtrickyだ。

【追記】 トリッキーと書いたが、むしろ本質の表れた定義だろう。

λ. 情報数学Ⅱ

ミニテスト。表を読み間違えてた。見栄を張って今日提出しなければ良かった。アホだな。アホすぎる。

欝だ、寝よう。

本日のツッコミ(全2件) [ツッコミを入れる]
ψ (2002-05-08 18:10)

Proc 生成してすぐさま call するなんて、脳が scheme に冒されて<br>いるとしか思えません。:-)<br><br>大して変わらないけど、書き変えてみました。<br><br>class Proc<br> def currying(arity=nil)<br> if self.arity >= 0<br> arity = self.arity<br> else<br> arity ||= (-self.arity)-1<br> end<br> <br> proc = lambda{|*args|<br> if args.size >= arity<br> call(*args)<br> else<br> lambda{|*a| proc.call(*(args + a))}<br> end<br> }<br> end<br>end<br><br>でも、n-arity が n 回 call で、本体が実行されるなら、n = 0 <br>では、最初から call されてしまうべきかもしれないなあ。仕様<br>が違うけどこんなのは?<br><br>class Proc<br> def currying(*args)<br> ari = arity >= 0 ? arity : -arity - 1<br><br> if ari <= args.size<br> call(*args)<br> else<br> lambda{|*a| currying(*(args + a))}<br> end<br> end<br>end<br> <br>if __FILE__ == $0<br> add = lambda{|a,b| a+b}.currying<br> succ = add[1]<br> p succ[100] #=> 101<br> p succ[3] #=> 4<br> <br> hello = lambda{puts "hello"}<br> hello.currying #=> hello<br><br> hello = lambda{|x,| puts "hello, " + x}.currying<br> hello["bye"] #=> hello, bye <br>end<br><br>こういう話は ruby-list でしたらもっといろんな意見がで<br>るかも。

ψ さかい (2002-05-09 00:28)

なるほど。そう書けばよかったのか。<br><br>schemeでコードを書いたことはほとんどないのだけど、<br>知らないうちに脳を冒されていたとは……scheme恐るべし。<br><br>n = 0 では 最初から call されてしまうべきってのも<br>確かにその通りですね。<br><br>ついでに、調子に乗って、<br>メソッドでも同じようなことを考えてみたのだけど、<br>どうもいまいち。ブロックの事も考えてないし。<br><br>require 'thread'<br><br>class Module<br> CURRYING_METHOD_TABLE_ = Array.new<br> CURRYING_METHOD_TABLE_MUTEX_ = Mutex.new<br><br> def currying(name, arity=nil)<br> m = instance_method(name)<br> <br> if m.arity == 0<br> return<br> elsif m.arity > 0<br> arity = m.arity<br> else<br> arity ||= (-m.arity)-1<br> end<br><br> tbl_idx = nil<br> CURRYING_METHOD_TABLE_MUTEX_.synchronize{<br> tbl_idx = CURRYING_METHOD_TABLE_.size<br> CURRYING_METHOD_TABLE_ << m<br> }<br><br> module_eval %Q[<br> def #{name.to_s}(*args1)<br> proc = lambda{|*args|<br> if args.size >= #{arity}<br> Module::CURRYING_METHOD_TABLE_[#{tbl_idx}].bind(self).call(*args)<br> else<br> lambda{|*a| proc.call(*(args + a))}<br> end<br> }<br> proc.call(*args1)<br> end<br> ]<br> end<br>end<br><br>class <<self<br> define_method(:currying, method(:currying).to_proc)<br>end<br><br>if __FILE__ == $0<br> def hello(a, out)<br> out.printf("Hello, %s!\n", a)<br> end<br> currying :hello<br><br> hello_ruby = hello("Ruby")<br> hello_ruby[STDOUT] #=> "Hello, Ruby!"<br>end