我最近尝试做类似的事情:
a = "some string"
b = Proc.new{ upcase }
a.instance_eval b
出现错误:
TypeError:无法将Proc转换为String
但这有效:
def b(&block)
"some string".instance_eval &block
end
b{ upcase }
使用此方法进一步了解:
def b(&block)
"some string".instance_eval block
end
产生相同的Proc to String
错误。
所以...我对积木的理解是它们只是触发器。但显然有一些关于这个&
&符号的特别之处......
有人可以向我解释一下吗?是否有可能将正常的proc转换为对这个&block
对象特殊的东西?
刚刚想出了我的第二个问题,在问题上添加了&
...这很容易,但这是真的在做什么?
答案 0 :(得分:22)
你需要做的第一个工作就是:
>> a.instance_eval &b #=> "SOME STRING"
原因是instance_eval
需要一个字符串或一个块,而&符号需要后者。
为了理解块和触发器之间的差异,可能以下博客文章有助于:
答案 1 :(得分:9)
不同之处在于 a.instance_eval b 将 b 作为instance_eval的常规参数传递,而 a.instance_eval& b 是把它作为一个块传递。这是两件不同的事情。
考虑这个方法调用:
obj.foo(bar)do | x |东西(x)结束
使用一个常规参数( bar )和一个块参数( do | x | stuff(x)end )调用方法 foo )。在方法定义中,它们通过在& 前加上块参数来区分:
def foo(arg,& block)
...
的端强>
如果你希望传递一个变量表达式而不是一个文字块,那么同样通过在表达式前面添加& 来实现这一点(它应该产生一个Proc)。
如果您传递的参数没有& ,则会进入 arg 插槽而不是块插槽。论证恰好是Proc的一个实例并不重要。语法规定了该方法如何传递和处理它。
答案 2 :(得分:1)
这是因为instance_eval接受一个字符串到eval或一个块。 instance_eval(&block)
正在将block
作为块传递给instance_eval。
答案 3 :(得分:1)
关键的区别在于一个Proc实例是一个对象而一个块不是一个对象。 &
是相互交换块和Proc实例的运算符。
方法的所有参数都必须是对象。除了参数之外,方法可以采用块。 instance_eval
是一个接受String参数或块的方法。传递Proc对象将既不满足也不满足。如果将&
附加到Proc对象,则将其作为块进行处理。
答案 4 :(得分:0)
这将有效:
a = "some string"
b = Proc.new{ upcase }
a.instance_eval &b
instance_eval
方法可以接收块参数。
b
是Proc
。