我有一个方法接受将被调用的lambda或将被评估的字符串。 为什么以下方法失败:
def test(expr)
expr = expr.respond_to?(:call) ? expr : ->{ eval(expr) }
expr.call
end
test 'puts 1'
# => TypeError: can't convert Proc into String
但这一项工作:
def test(expr)
foo = expr
expr = expr.respond_to?(:call) ? expr : ->{ eval(foo) }
expr.call
end
test 'puts 1'
# => 1
答案 0 :(得分:3)
您正在将lambda分配给变量expr
。该lambda试图评估变量expr
的内容(即尝试评估自己)。 eval
只需要字符串,这就是引发异常的原因。
答案 1 :(得分:3)
在这里:
expr = expr.respond_to?(:call) ? expr : ->{ eval(expr) }
你最终得到的expr
中的Proc是expr
的封闭,因此当评估Proc时,它会尝试eval
本身,因为expr
里面的foo = expr
expr = expr.respond_to?(:call) ? expr : ->{ eval(foo) }
lambda就是lambda本身。
在这里:
foo
闭包超过expr
,它引用eval
的原始字符串值,因此没有时髦的自引用混淆,你最终会在字符串上使用{{1}}。