为什么明确的回报在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"
我认为在Ruby中return
关键字是可选的,并且无论您是否请求,您总是return
。 鉴于此,我发现foo
和bar
具有不同的输出,这是由foo
在Proc f
包含显式return
这一事实决定的。
有谁知道这是为什么?
Ruby有三个构造:
- 块不是一个对象,由
{
…}
或do
…end
。 - proc是由
Proc.new
或proc
创build的Proc
对象。 - lambda是由
lambda
创build的Proc
(或者Ruby 1.8中的proc
)。
Ruby有三个从某些东西返回的关键字:
-
return
终止方法或lambda它在。 -
next
终止它所在的块,proc或lambda。 -
break
终止产生到块的方法或调用它所在的proc或lambda。
在lambdaexpression式中,无论出于何种原因, return
行为都像next
。 next
和break
是按照它们的方式命名的,因为它们通常与each
方法一起使用,在这些方法中,终止块将导致迭代继续执行集合的下一个元素,并终止each
元素将导致您跳出循环。
如果在foo
的定义中使用return
,即使它在一个块或一个proc中,也将从foo
返回。 要从块返回,可以使用next
关键字。
def foo f = Proc.new { next "return from foo from inside proc" } f.call # control leaves foo here return "return from foo" end puts foo # prints "return from foo"
这是Proc
的语义; 它不一定是所有块的语义。 我同意这有点混乱。 这是为了增加灵活性(也许部分导致Ruby除了实现之外没有规范)。
行为在Proc
实现中定义。 Lambda
的行为是不同的,所以如果你想让你的return
不能退出封闭的方法,请使用lambdas 。 或者,省略Proc
的return
关键字。
Rubysclosures的深入调查在这里 。 这是一个梦幻般的揭露。
所以:
def foo f = Proc.new { p2 = Proc.new { return "inner proc"}; p2.call return "proc" } f.call return "foo" end def foo2 result = Proc.new{"proc"}.call "foo2 (proc result is: #{result})" end def bar l = lambda { return "lambda" } result = l.call return "bar (lambda result is: #{result})" end puts foo # inner proc puts foo2 # foo (proc result is: proc) puts bar # bar (lambda result is: lambda)
想想这样:Proc.new只需创build一个代码块,这是调用函数的一部分。 proc / lambda创build一个具有特殊绑定的匿名函数。 一些代码示例将有所帮助:
def foo f = Proc.new { return "return from foo from inside Proc.new" } f.call # control leaves foo here return "return from foo" end
相当于
def foo begin return "return from foo from inside begin/end" } end return "return from foo" end
所以很明显,返回将从函数'foo'
相反:
def foo f = proc { return "return from foo from inside proc" } f.call # control stasy in foo here return "return from foo" end
相当于(忽略绑定,因为在这个例子中没有使用):
def unonymous_proc return "return from foo from inside proc" end def foo unonymous_proc() return "return from foo" end
这显然不会从foo返回,而是继续到下一个语句。