正如我所理解的,Proc
中的return
终止了当前方法。因此,在以下示例中,我希望看到:a1>b1>proc>a2.但实际上它从来没有达到a2,为什么?
def a
puts "a1"
l = Proc.new {puts "proc"; return}
b l
puts "a2"
end
def b x
puts "b1"
x.call
puts "b2"
end
a
作为一般规则,return
总是从最接近的词法封闭方法定义表达式返回。
在这种情况下,最接近的词法封闭方法定义表达式是def a
,因此,return
从a
返回。
在这种情况下,return
在块内实际上并不重要。一般规则是一般的,所以无论return
出现在哪里,它都适用。
然而,如果我们更具体地观察块,我们可以看到这仍然是有意义的:在块中,局部变量是用词汇捕获的,self
是用词汇捕捉的,所以return
也有词汇行为是有意义。块的一个一般性质是,如果你想了解块中发生了什么,你只需要从词汇上向外看。
如果我们更具体地说,首先从一般规则到块,现在从块到Proc
s,这种行为仍然是有意义的:Proc
本质上是一个具体化的块,所以Proc
表现得像块是有道理的。
不过,一般规则有一些例外,其中一个重要的例外是lambdas。在Ruby中谈论lambdas总是有点奇怪,因为lambdas是Proc
s,但它们的行为与Proc
s不同。IMO,lambdas应该与Proc
s一起有一个单独的类。由于lambdas为Proc
s,谈论Lambda和CCD_ 18s之间的差异是很奇怪的,它们不是Lambda(它们没有标准化的名称,因此也被混淆地称为Proc
s(。
lambda的行为与非lambdaProc
的行为在两个方面不同,其中一个与您的问题有关:
- 非lambda
Proc
s中的参数绑定与块中的参数捆绑具有相同的语义,而lambdas中的参数约束与消息发送/方法调用中的参数结合具有相同的语法 - 在非lambda
Proc
s中,return
从最接近的词法封闭方法定义表达式返回,就像在块中一样,而在lambda中,return
从lambda本身返回,就像方法中的return
一样
因此,在这两个方面,非lambdaProc
s的行为类似于块,lambda的行为类似于方法。我是这样记住的:;CCD_ 27";与";块";并且两者";λ";以及";方法";是希腊语。
正如您可能知道的,有一些方法也会改变传递给它们的块的行为。例如,instance_eval
和instance_exec
改变了self
的值,而define_method
实际上改变了return
的行为。
但是,由于您没有询问一般的块,也没有专门询问lambda,并且您的问题中没有反射方法,因此一般规则仍然适用于非lambdaProc
,如您的问题所示:return
从最接近的词法封闭方法定义表达式返回。