Ruby 块、procs 和 instance_eval

发布于 2024-11-16 00:38:58 字数 661 浏览 8 评论 0原文

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

怎言笑 2024-11-23 00:38:58

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

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

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

All you have to do for your first example to work is this:

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

The reason is that instance_eval needs either a string or a block and the ampersand provides the latter.

裸钻 2024-11-23 00:38:58

区别在于,a.instance_eval bb 作为常规参数传递给 instance_eval,而 a.instance_eval &b 将其作为常规参数传递一个块。这是两件不同的事情。

考虑这个方法调用:

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

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

def foo(arg, &block)

如果您希望传递变量表达式而不是文字块,同样可以通过添加前缀 & 来实现; 到表达式(应该产生一个 Proc)。

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

The difference is that a.instance_eval b is passing b as a regular argument to instance_eval, whereas a.instance_eval &b is passing it as a block. Those are two different things.

Consider this method call:

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

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:

def foo(arg, &block)

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.

人心善变 2024-11-23 00:38:58

这是因为 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 your block as a block to instance_eval.

弱骨蛰伏 2024-11-23 00:38:58

关键的区别在于,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.

梦里梦着梦中梦 2024-11-23 00:38:58

这将起作用:

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

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

This will work:

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

The instance_eval method can receive an block arguments.
b is a Proc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文