Ruby 块、procs 和 instance_eval
我最近尝试做类似的事情:
a = "some string"
b = Proc.new{ upcase }
a.instance_eval b
这给出了错误:
类型错误:无法将 Proc 转换为字符串
但这有效:
def b(&block)
"some string".instance_eval &block
end
b{ upcase }
使用此方法进一步查看:
def b(&block)
"some string".instance_eval block
end
产生相同的 Proc to String
错误。
所以...我对块的理解是它们只是过程。但显然这个 &
&符号有一些特别之处......
有人可以向我解释一下吗?是否可以将普通过程转换为此 &block
对象的特殊内容?
编辑
刚刚弄清楚我的第二个问题,在过程中添加一个 &
...这很简单,但这到底是做什么的?
I recently tried to do something akin to this:
a = "some string"
b = Proc.new{ upcase }
a.instance_eval b
Which gives the error:
TypeError: can't convert Proc into String
but this works:
def b(&block)
"some string".instance_eval &block
end
b{ upcase }
A further look with this method:
def b(&block)
"some string".instance_eval block
end
Yields the same Proc to String
error.
So... my understanding of blocks is that they are just procs. But there's obviously something special about having this &
ampersand...
Can someone explain this to me? Is it possible to convert a normal proc to be whatever it is that is special about this &block
object?
edit
Just figured out my second question, prepend an &
to the proc... that was easy, but WHAT is this really doing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
要使第一个示例正常工作,您所需要做的就是:
原因是
instance_eval
需要字符串或块,而 & 符号提供后者。All you have to do for your first example to work is this:
The reason is that
instance_eval
needs either a string or a block and the ampersand provides the latter.区别在于,
a.instance_eval b
将b
作为常规参数传递给 instance_eval,而a.instance_eval &b
将其作为常规参数传递一个块。这是两件不同的事情。考虑这个方法调用:
它使用一个常规参数 (
bar
) 和一个块参数 (do |x| stuff(x) end
do |x| stuff(x) endfoo 来调用方法代码>)。在方法定义中,通过在块参数前添加前缀&
来区分它们:如果您希望传递变量表达式而不是文字块,同样可以通过添加前缀 & 来实现; 到表达式(应该产生一个 Proc)。
如果传递不带
&
的参数,它将进入 arg 槽,而不是 block 槽。参数恰好是 Proc 的实例并不重要。语法规定了方法如何传递和处理它。The difference is that
a.instance_eval b
is passingb
as a regular argument to instance_eval, whereasa.instance_eval &b
is passing it as a block. Those are two different things.Consider this method call:
That invokes the method
foo
with one regular argument (bar
) and one block argument (do |x| stuff(x) end
). In the method definition, they're distinguished by prefixing&
to the block parameter:And if you wish to pass a variable expression instead of a literal block, that is likewise accomplished by prefixing & to the expression (which should yield a Proc).
If you pass an argument with no
&
, it goes in the arg slot instead of the block slot. It doesn't matter that the argument happens to be an instance of Proc. The syntax dictates how it is passed and treated by the method.这是因为 instance_eval 接受要 eval 的字符串或块。
instance_eval(&block)
正在将您的block
作为块传递给 instance_eval。It's because instance_eval accepts a string to eval or a block.
instance_eval(&block)
is passing yourblock
as a block to instance_eval.关键的区别在于,Proc 实例是对象,而块不是对象。
&
是一个相互交换块和Proc实例的运算符。方法的所有参数都必须是对象。除了参数之外,方法还可以采用块。
instance_eval
是一种采用字符串参数或块的方法。传递 Proc 对象不会满足这两种情况。如果将&
附加到 Proc 对象,它将作为块进行处理。The crucial difference is that a Proc instance is an object whereas a block is not an object. The
&
is an operator that interchanges a block and a Proc instance mutually.All arguments to a method must be an object. In addition to the arguments, a method can take a block.
instance_eval
is a method that takes either a String argument or a block. Passing a Proc object will satisfy neither case. If you attach&
to a Proc object, that will be handeled as a block.这将起作用:
instance_eval
方法可以接收块参数。b
是一个Proc
。This will work:
The
instance_eval
method can receive an block arguments.b
is aProc
.