今読んでる「ハッカーと画家」にこんなRubyのサンプルコードが載ってました。
def foo(n) lambda {|i| n += i} end
本の解説によるとこれは「数nを取り、『数iを取ってnをiだけ増加させ、その増加した値を返す関数』を返す関数」というアキュムレータ(累積器)だそうです。
本を読んだだけではピンとこなかったので実際に動かしてみました。
def foo(n) lambda {|i| n += i} end x = foo 1 p x.call 1 p x.call 2 p x.call 3 p x.call 0 p x.call -1
実行結果は以下の通りです。
2 4 7 7 6
これを見てどういうプログラムか分かりましたか?
僕は実行結果を見てもしばらく意味がわかりませんでした・・・。
が、よく見るとこういうことだったんですね。
x = foo 1 #初期値が1 p x.call 1 #1+1=2 p x.call 2 #2+2=4 p x.call 3 #4+3=7 p x.call 0 #7+0=7 p x.call -1 #7-1=6
前の計算の値がxの中に保持されているイメージです。
なんか意外ですね。
lambdaについてもうちょっと調べてみようと「プログラミング言語Ruby」を読んでいたところ、Ruby1.9ではlambdaの新しい構文がサポートされたと書いてありました。
その構文を使って最初のコードを書き直してみました。
def foo(n) ->(i){n += i} end x = foo 1 p x.call 1 #以下略
fooの定義までlambdaにしてしまうとこんな感じです。
foo = ->(n){->(i){n += i}} x = foo.call 1 p x.call 1 #以下略
メソッドが終了した後の変数の保持については「プログラミング言語Ruby」の「6.6 クロージャ」のあたりに詳しく書いてあります。
まあ正直、このあたりは難しすぎて完全には理解できていないですけどね・・・。(- -;;
こんなコードを実務で書く機会はほとんどないでしょうが、動きが面白かったので載せてみました。
ご参考までに。
参考文献
- 作者: ポールグレアム,Paul Graham,川合史朗
- 出版社/メーカー: オーム社
- 発売日: 2005/01/01
- メディア: 単行本
- 購入: 109人 クリック: 4,884回
- この商品を含むブログ (582件) を見る
- 作者: まつもとゆきひろ,David Flanagan,卜部昌平(監訳),長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2009/01/26
- メディア: 大型本
- 購入: 21人 クリック: 356回
- この商品を含むブログ (129件) を見る