繁体   English   中英

Ruby 块、procs 和 instance_eval

[英]Ruby block, procs and instance_eval

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

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

这给出了错误:

类型错误:无法将 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对象的特殊之处?

编辑

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

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

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

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

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

考虑这个方法调用:

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

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

def foo(arg, &block)

如果你想传递一个变量表达式而不是一个文字块,同样可以通过在表达式前加上&来实现(它应该产生一个 Proc)。

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

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

关键的区别在于Proc 实例是一个对象,块不是一个对象 &是一个操作符,可以相互交换块和 Proc 实例

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

这将起作用:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM