Rubyのlambda,proc関数の使い方が良く分かりません。

「こういうときに使うと便利」という例があれば教えてください。

回答の条件
  • URL必須
  • 1人10回まで
  • 登録:
  • 終了:2007/11/27 12:21:52
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答5件)

id:dankogai No.1

回答回数2ベストアンサー獲得回数0

ポイント20pt

手前味噌を一つ。

Dan.the.Occasional.Rubyist

id:garyo

ありがとうございます。

カリー化が複数の引数を持つ関数を1つの引数の関数にすることらしく、確かにlog a Xが引数1つづつの関数で表されているのは分かったのですが、引数を1つの関数にするとどういうメリットがあるのかまだ良く分かっていません。

2007/11/24 23:32:28
id:cuzic No.2

回答回数10ベストアンサー獲得回数1

ポイント20pt

http://www.yahoo.co.jp/

URL はダミーです。

lambda とか proc とかを使うと、ある種の手続きをオブジェクトにすることができて、引数などとして渡すことができるようになります。

そうすると、たとえば /aaa/ にマッチするときは、文字列を xxx と処理して、/bbb/ にマッチするときは yyy のように処理するということができるようになります。

同じようなことは、ファクトリーパターン+継承(ポリモーフィズム)でできますが、lambda を使った方が簡潔です。

id:garyo

ありがとうございます。

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はオブジェクト指向言語ですが、関数言語の機能も含んでいるのでしょうか。

2007/11/25 23:54:37
id:tociyuki No.3

回答回数12ベストアンサー獲得回数1

ポイント20pt

ファイナライザを定義するときに使います。

http://www.ruby-lang.org/ja/man/?cmd=view;name=ObjectSpace

id:garyo

ありがとうございます。

デストラクタに「やること」を引数で渡すわけですね。

def initialize と同様に def finalizer のように定義するのかと思っていました。

2007/11/25 15:36:39
id:kazutanaka No.4

回答回数4ベストアンサー獲得回数1

ポイント20pt

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}
id:garyo

詳しく説明頂きありがとうございます。

>つまりブロックが使えていれば、lambdaを使いこなせているのです。

procが使えれば大体使いこなせていてさらに細かな動作をさせたいときにlambdaを使うというイメージでしょうか。

lambdaがλ関数であればチューリングマシンと同値。つまりlambda関数さえあれば全てのプログラムが記述可能なわけでしょうか。

mixiの某トピで「yieldとblock.callどっちを使いますか」というのがあってblock.callが良く分からなかったのですが、説明を見て分かったような気がします。

C/C++/Java/C#などには「クロージャー」の概念がないので凄く興味があります。

以前、以下の質問でRubyを薦めたのですが、質問者の方はPHPを選ばれたので残念に思ったことがあります。

Rubyには他の言語にない先進的(逆にLispから受け継いだのでいにしえの術かも)な機能があるのでそれを説明したかったのですが、言葉で表せなかったのが残念です。Rubyを使っているだけで色々勉強になります。

http://q.hatena.ne.jp/1194256707

2007/11/26 00:46:08
id:kazutanaka No.5

回答回数4ベストアンサー獲得回数1

ポイント20pt

>procが使えれば大体使いこなせていて

>さらに細かな動作をさせたいときに

>lambdaを使うというイメージでしょうか。


Proc.new, proc{}, lambda{} は同じものです。

(微妙な違いはありますが)

それらを直接使うことはあまり必要ないでしょう。


ほとんどの場合、より高度な構文である

ブロックだけで済んでしまうのです。

(昔はイテレータ、今はブロックと呼びます)


ブロックには「関数に1つしか受け渡せない」

「変数に代入できない」という制約があり、

それを超えてコードの受け渡しをしたいときには

lambdaを明示的に使わないとできません。


>lambdaがλ関数であればチューリングマシンと同値。

>つまりlambda関数さえあれば全てのプログラムが記述可能なわけでしょうか。


ラムダ関数は単なる語源ぐらいに考えた方が現実的だと思います。

Rubyのlambdaは単純にコードをオブジェクト化しているだけです。

回り道かもしれませんが、LispかSchemeを学んだらいいのでは?


http://practical-scheme.net/gauche/index-j.html

id:garyo

ありがとうございます。

>ブロックには「関数に1つしか受け渡せない」

>「変数に代入できない」という制約があり、

>それを超えてコードの受け渡しをしたいときには

>lambdaを明示的に使わないとできません。

なるほど、そういうわけなんですね。良く分かりました。

2007/11/26 07:29:55
  • id:garyo
    >遅延評価 とか、無限データ構造 とか、 カリー化 とか
    って何でしょう?
    λ式で書けるものは計算可能なものと同値とか、Lispはλ式を計算するための言語だとか・・・
    謎は深まるばかりです

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません