Weird Proc error in Ruby
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.
精彩评论