Archive for category 勉強記録

僕の考えたカリー化

カリー化とは

複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること。


http://wiki.onakasuita.org/pukiwiki/?%E3%82%AB%E3%83%AA%E3%83%BC%E5%8C%96

http://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AA%E3%83%BC%E5%8C%96
など参考

最近は「関数が第一級のオブジェクト」、要は「手続きの固まり」を文字列や数字のようにモノ扱いできる、RubyやJavaScriptのような言語が普及しているが、そういう言語では「カリー化」の手法が使える。

例えばRubyで、x個の、yから始まる数の総和を求めるorigという関数を考える。

1
2
3
4
5
6
7
def orig(x, y)
  ret = 0
  for i in y..(x + y - 1) do
    ret += i
  end
  return ret
end

(※)

このorig(x, y)を元に、「3個」「4個」「5個」の、yから始まる数の総和を求める関数を作りたい。下の如し。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def curried_orig(x)
  lambda do |y|
    orig(x, y)
  end
end
 
sum3 = curried_orig(3)
#=> #<Proc:0x0000002a955cf098>
sum4 = curried_orig(4)
#=> #<Proc:0x0000002a955cf098>
sum5 = curried_orig(5)
#=> #<Proc:0x0000002a955cf098>
sum3[10]
#=> 10+11+12 = 33
sum4[10]
#=> 10+11+12+13 = 46
sum5[10]
#=> 10+11+12+13+14 = 60

sum3やsum4に束縛されるのは、実際にはメソッドというよりProcオブジェクトなので、()ではなく[]で呼び出す。

Ruby1.9.1からは「Proc#curry」が導入され、よりすっきり書ける。

1
2
3
4
5
6
7
8
9
10
sum_x = lambda {|x, y|
  ret = 0
  for i in x...(x + y) do
    ret += i
  end
  return ret
}
sum3 = sum_x.curry[3]
sum3[10]
#=> 10+11+12 = 33

数学的な概念は良く分かっていないけど。

http://www.nslabs.jp/closure.rhtml

「カリー化」とは (A, B) -> C という関数をA -> (B -> C) という関数に変換することです。


http://www.khelll.com/blog/ruby/ruby-currying/

Check this function f which takes 3 params x,y,z

f(x,y,z) = 4*x+3*y+2*z

Currying means that we can rewrite the function as a composition of 3 functions(a function for each param):

f(x)(y)(z) = 2*z+(3*y+(4*x))

http://www.ruby-forum.com/topic/142699#633354

It’s not difficult at all,

1
  proc {|x, y, z| x + y + z }.curry

returns the proc object equivalent to

1
  proc {|x| proc {|y| proc {|z| x + y + z } } }

実際利用する時に「関数の部分適用」と「カリー化」を区別する意味ってあまり無いかもしれないんだけど。「Proc#curry」はこういう意味ですよ、というのは認識したほうがいいのかも。

その他のカリー化の使い方例 参考:「Fun with Procs in Ruby 1.9」
http://pragdave.blogs.pragprog.com/pragdave/2008/09/fun-with-procs.html

* * *

※: 個人的に普段はこう書いてしまい俺気持ちが悪い。

1
2
3
def orig(x, y)
  (0...x).to_a.map{|v| y + v}.inject{|d, s| d += s}
end

関数型っぽい言語を比較 – Quick Sort編 -

関数型な書き方が得意な言語を比較。目に付いたモノを一通り見ただけの自分メモです。。

Read the rest of this entry »

受けたい資格とか考えてみた

基本情報処理技術者試験の合格発表日です。受けた方々はお疲れ様でした。僕は応用情報を受けたので、来月半ばまでは落ち着かない日々ですが。。。

そんな日に資格について考えてみた。今日池袋のジュンク堂寄ってきたので、ついでにじろじろ見てきたこともあり。

Read the rest of this entry »