I have a method accepting a lambda which will be called or a string which will be evaluated. Why does the fo开发者_运维问答llowing method fail:
def test(expr)
expr = expr.respond_to?(:call) ? expr : ->{ eval(expr) }
expr.call
end
test 'puts 1'
# => TypeError: can't convert Proc into String
But this one work:
def test(expr)
foo = expr
expr = expr.respond_to?(:call) ? expr : ->{ eval(foo) }
expr.call
end
test 'puts 1'
# => 1
In here:
expr = expr.respond_to?(:call) ? expr : ->{ eval(expr) }
You end up with a Proc in expr that is a closure over expr so when the Proc is evaluated, it tries to eval itself because the expr inside the lambda is the lambda itself.
In here:
foo = expr
expr = expr.respond_to?(:call) ? expr : ->{ eval(foo) }
the closure is over foo which refers to the original String value of expr so there is no funky self-referential confusion and you'll end up using eval on a String.
You are assigning lambda to variable expr. That lambda tries to eval content of variable expr (i.e. tries to eval itself). eval expects only string, that is why exception is raised.
加载中,请稍侯......
精彩评论