16

我最近尝试做类似的事情:

a = "some string"
b = Proc.new{ upcase }
a.instance_eval b

这给出了错误:

TypeError:无法将 Proc 转换为字符串

但这有效:

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

编辑

刚刚想出了我的第二个问题,&在 proc 前面加上一个……这很容易,但这到底在做什么?

4

5 回答 5

24

要使您的第一个示例正常工作,您所要做的就是:

>> a.instance_eval &b #=> "SOME STRING"

原因是它instance_eval需要一个字符串或一个块,而&符提供后者。

于 2011-06-16T13:29:18.097 回答
11

不同之处在于它作为常规参数a.instance_eval b传递给 instance_eval,而将其作为块传递。这是两个不同的东西。 ba.instance_eval &b

考虑这个方法调用:

obj.foo(bar) do |x| 
  stuff(x) 
end

foo它使用一个常规参数 ( bar) 和一个块参数 ( )调用该方法do |x| stuff(x) end。在方法定义中,它们通过&在块参数前加前缀来区分:

def foo(arg, &block)

如果您希望传递变量表达式而不是文字块,这同样可以通过在表达式前加上&来完成(这应该产生一个 Proc)。

如果您传递带有 no 的参数&,它将进入arg槽而不是槽。参数恰好是 Proc 的一个实例并不重要。语法规定了方法如何传递和处理它。

于 2011-06-17T02:36:09.610 回答
1

这是因为 instance_eval 接受一个字符串来 eval 或一个块。instance_eval(&block)将您block作为一个块传递给 instance_eval。

于 2011-06-16T13:27:27.800 回答
1

关键的区别在于Proc 实例是一个对象,而块不是一个对象。The&相互交换块和 Proc 实例的运算符。

方法的所有参数都必须是对象。除了参数之外,方法还可以采用块。instance_eval是一个接受字符串参数或块的方法。传递 Proc 对象将满足这两种情况。如果您附加&到 Proc 对象,它将作为一个块处理。

于 2011-06-16T13:42:09.707 回答
0

这将起作用:

a = "some string"
b = Proc.new{ upcase }
a.instance_eval &b

instance_eval方法可以接收块参数。 b是一个Proc

于 2013-08-11T08:05:33.117 回答