2011-09-12 6 views
3

私は、呼び出されるラムダを受け入れるメソッドまたは評価される文字列を受け取ります。 はなぜ以下の方法が失敗しない:ルビーの奇妙なProcエラー

def test(expr) 
    expr = expr.respond_to?(:call) ? expr : ->{ eval(expr) } 
    expr.call 
end 

test 'puts 1' 
# => TypeError: can't convert Proc into String 

しかし、この1つの作業:

def test(expr) 
    foo = expr 
    expr = expr.respond_to?(:call) ? expr : ->{ eval(foo) } 
    expr.call 
end 

test 'puts 1' 
# => 1 
+0

Typo?本当に綴られたepr? –

+0

ええ、訂正しました。 –

+1

あなたが2つの良い答えを持っているのを見てうれしい。 –

答えて

3

ここでは:ラムダ内部exprはラムダ自体があるので

expr = expr.respond_to?(:call) ? expr : ->{ eval(expr) } 

あなたは、PROCが評価されるので、expr以上の閉鎖があることexprにPROCで終わる、それはevalに自分自身をしようとします。

ここで:

foo = expr 
expr = expr.respond_to?(:call) ? expr : ->{ eval(foo) } 

exprの元の文字列の値を参照するので、そこにはファンキーな自己参照の混乱はありません、あなたは文字列にevalを使用して終わるだろうどのfoo上閉鎖があります。

+0

ありがとうございました。 –

+0

@ ream88:ビクターが最初に入っていたので、チェックマークを付けるべきです(私は個人的には正直ではありません)、何が起こっているのかを明確にしようとしていました。 –

+0

"自己参照"を呼び出すための+1。あなたの答えははるかに分かりやすいです;)(アップワードされた勝者は答える) –

3

あなたは、変数exprにラムダを割り当てています。ラムダは変数exprの内容を評価しようとします(つまり、評価自体を試みます)。 evalは文字列のみを必要とするため、例外が発生します。