为什么显式返回在 Proc 中会产生影响?
def foo
f = Proc.new { return "return from foo from inside proc" }
f.call # control leaves foo here
return "return from foo"
end
def bar
b = Proc.new { "return from bar from inside proc" }
b.call # control leaves bar here
return "return from bar"
end
puts foo # prints "return from foo from inside proc"
puts bar # prints "return from bar"
我认为 return
关键字在 Ruby 中是可选的,并且无论您是否请求,您总是会 return
。鉴于此,我发现令人惊讶的是 foo
和 bar
具有不同的输出,这是由 foo
包含显式 return
的事实决定的Proc f
中的 code>。
有谁知道为什么会这样?
def foo
f = Proc.new { return "return from foo from inside proc" }
f.call # control leaves foo here
return "return from foo"
end
def bar
b = Proc.new { "return from bar from inside proc" }
b.call # control leaves bar here
return "return from bar"
end
puts foo # prints "return from foo from inside proc"
puts bar # prints "return from bar"
I thought the return
keyword was optional in Ruby and that you are always return
ing whether you request it or not. Given that, I find it surprising that foo
and bar
have different output determined by the fact that foo
contains an explicit return
in Proc f
.
Does anyone know why this is the case?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Ruby 具有三种结构:
{
...}
或do
创建的...结束
。Proc.new
或proc
创建的Proc
对象。lambda
(或 Ruby 1.8 中的proc
)创建的Proc
。Ruby 具有三个从某些内容返回的关键字:
return
终止它所在的方法或 lambda。next
终止它所在的块、proc 或 lambda。break
终止生成块或调用其所在的 proc 或 lambda 的方法。在 lambda 中,无论出于何种原因,
return
的行为类似于next
。next
和break
之所以如此命名,是因为它们最常与each
等方法一起使用,其中终止块将导致迭代继续使用集合的下一个元素,终止每个
将导致您中断跳出循环。If you use
return
inside the definition offoo
, you will return fromfoo
, even if it is inside a block or a proc. To return from a block, you can use thenext
keyword instead.Ruby has three constructs:
{
...}
ordo
...end
.Proc
object created byProc.new
orproc
.Proc
created bylambda
(orproc
in Ruby 1.8).Ruby has three keywords that return from something:
return
terminates the method or lambda it is in.next
terminates the block, proc, or lambda it is in.break
terminates the method that yielded to the block or invoked the proc or lambda it is in.In lambdas,
return
behaves likenext
, for whatever reason.next
andbreak
are named the way they are because they are most commonly used with methods likeeach
, where terminating the block will cause the iteration to resume with the next element of the collection, and terminatingeach
will cause you to break out of the loop.If you use
return
inside the definition offoo
, you will return fromfoo
, even if it is inside a block or a proc. To return from a block, you can use thenext
keyword instead.这是
Proc
的语义;它不一定是所有块的语义。我同意这有点令人困惑。它的存在是为了增加灵活性(也许部分原因是 Ruby 除了其实现之外没有规范)。该行为在
Proc
实现中定义。Lambda
的行为有所不同,因此如果您希望返回不退出封闭方法,请使用 lambda强>。或者,从您的Proc
中省略return
关键字。对 Ruby 闭包的深入研究在这里。这是一次精彩的曝光。
所以:
This is the semantics for
Proc
s; it is not necessarily the semantics for all blocks. I agree this is a bit confusing. It is there for added flexibility (and perhaps partially cause Ruby has no spec except for its implementation).The behavior is defined in the
Proc
implementation.Lambda
s behave differently, so if you would like yourreturn
s not to exit out of the enclosing method, use lambdas. Or, omit thereturn
keyword from yourProc
.A deep investigation of Rubys closures is here. It is a fantastic exposé.
So:
这样想:Proc.new 只是创建一个作为调用函数一部分的代码块。 proc/lambda 创建一个具有特殊绑定的匿名函数。一些代码示例会有所帮助:
相当于
所以很明显,返回将仅从函数“foo”返回
相比之下:
相当于(忽略绑定,因为在本示例中未使用):
这显然不会从 foo 返回并继续执行下一条语句。
Think of it this way: Proc.new just create a block of code that is part of the calling function. proc/lambda create an anonymous function that has special bindings. A little code examples will help:
is equivalent to
so it is clear that the return will just return from the function 'foo'
in contrast:
is equivalent to (ignoring the bindings since not used in this example):
Which is as clearly will not return from foo and continue to the next statement instead.