「こういうときに使うと便利」という例があれば教えてください。
手前味噌を一つ。
Dan.the.Occasional.Rubyist
URL はダミーです。
lambda とか proc とかを使うと、ある種の手続きをオブジェクトにすることができて、引数などとして渡すことができるようになります。
そうすると、たとえば /aaa/ にマッチするときは、文字列を xxx と処理して、/bbb/ にマッチするときは yyy のように処理するということができるようになります。
同じようなことは、ファクトリーパターン+継承(ポリモーフィズム)でできますが、lambda を使った方が簡潔です。
ありがとうございます。
CやC++ではその概念がない(コールバック関数とか、関数ポインタはありますが)ので、どのような時に使うと便利なのか分からず質問してみました。
ブロックを引数にとるイテレーターがすごく便利なのは実感していますが、手続き({puts x}みたいな)を変数に入れて(a=proc{|x|puts x};a[1])使う場面というのが中々想像できないです。lispとかやられてた方には自明なのでしょうか?
後、lambda関数とλ計算は同じものなのでしょうか?http://d.hatena.ne.jp/keyword/%a6%cb%b7%d7%bb%bb
上記に書いてあるλを使った式はlambdaでも書けるのでしょうか?
Rubyはオブジェクト指向言語ですが、関数言語の機能も含んでいるのでしょうか。
ありがとうございます。
デストラクタに「やること」を引数で渡すわけですね。
def initialize と同様に def finalizer のように定義するのかと思っていました。
http://capsctrl.que.jp/kdmsnr/wiki/bliki/?Closure
Rubyのブロックは、関数内部で暗黙にProcオブジェクトに変換されています。
ブロックはlambda,procのシンタックスシュガーと考えればよいでしょう。
つまりブロックが使えていれば、lambdaを使いこなせているのです。
上記の記事でMartin Fowlerも明示的にlambdaを使うことは少ないと書いています。
ブロックは末尾引数に&を付ければ受け取ることができ、
その値はProcオブジェクトになります。
def setBehaviour(&block) @block = block # block.class => Proc end def doBehaviour @block.call("hoge") end setBehaviour() {|x| puts x} doBehaviour()
ブロックのままだとメソッド内でyieldするしかありませんが、
ブロックがProcになると変数に代入できるので、
変数に記憶しておけば、同じ動作を繰り返し使えるようになります。
コードをブロックで渡すだけで済むなら、ブロックでよいのです。
しかし、コードをブロック形式で渡せない状況であれば
lambdaを明示的に使うことになるでしょう。
例えば、複数のコードブロックを渡したい場合とか、
名前付き引数でコードブロックを指定する時とかが思いつきます。
http://api.rubyonrails.org/classes/ActiveRecord/Validations/Clas...
たまたま開いていた上のActiveRecordのvalidationでもlambdaを使ってますね。
class Person < ActiveRecord::Base validates_numericality_of :value, :on => :create, :if => lambda { |user| user.signup_step > 2 } end
こういうのはフレームワーク側で面倒見切れないので、
利用者側が外部からlambdaで指定するわけです。
http://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B...
もしlambdaを使いこなしたいのであれば、引数で受け渡せることに加えて
レキシカルクロージャという概念も知っておいた方がよいでしょう。
上のWikipeadiaのJavaScriptカウンタをrubyで書いてみるとこんな感じ。
def make_counter(base=0, inc=1) lambda {base+=inc} end c = make_counter(1,2) 10.times {puts c.call}
詳しく説明頂きありがとうございます。
>つまりブロックが使えていれば、lambdaを使いこなせているのです。
procが使えれば大体使いこなせていてさらに細かな動作をさせたいときにlambdaを使うというイメージでしょうか。
lambdaがλ関数であればチューリングマシンと同値。つまりlambda関数さえあれば全てのプログラムが記述可能なわけでしょうか。
mixiの某トピで「yieldとblock.callどっちを使いますか」というのがあってblock.callが良く分からなかったのですが、説明を見て分かったような気がします。
C/C++/Java/C#などには「クロージャー」の概念がないので凄く興味があります。
以前、以下の質問でRubyを薦めたのですが、質問者の方はPHPを選ばれたので残念に思ったことがあります。
Rubyには他の言語にない先進的(逆にLispから受け継いだのでいにしえの術かも)な機能があるのでそれを説明したかったのですが、言葉で表せなかったのが残念です。Rubyを使っているだけで色々勉強になります。
>procが使えれば大体使いこなせていて
>さらに細かな動作をさせたいときに
>lambdaを使うというイメージでしょうか。
Proc.new, proc{}, lambda{} は同じものです。
(微妙な違いはありますが)
それらを直接使うことはあまり必要ないでしょう。
ほとんどの場合、より高度な構文である
ブロックだけで済んでしまうのです。
(昔はイテレータ、今はブロックと呼びます)
ブロックには「関数に1つしか受け渡せない」
「変数に代入できない」という制約があり、
それを超えてコードの受け渡しをしたいときには
lambdaを明示的に使わないとできません。
>lambdaがλ関数であればチューリングマシンと同値。
>つまりlambda関数さえあれば全てのプログラムが記述可能なわけでしょうか。
ラムダ関数は単なる語源ぐらいに考えた方が現実的だと思います。
Rubyのlambdaは単純にコードをオブジェクト化しているだけです。
回り道かもしれませんが、LispかSchemeを学んだらいいのでは?
ありがとうございます。
>ブロックには「関数に1つしか受け渡せない」
>「変数に代入できない」という制約があり、
>それを超えてコードの受け渡しをしたいときには
>lambdaを明示的に使わないとできません。
なるほど、そういうわけなんですね。良く分かりました。
ありがとうございます。
カリー化が複数の引数を持つ関数を1つの引数の関数にすることらしく、確かにlog a Xが引数1つづつの関数で表されているのは分かったのですが、引数を1つの関数にするとどういうメリットがあるのかまだ良く分かっていません。