proc和method或lambda之间的一个重要区别在于它们处理return语句的方式。如果一个方法被定义在另一个方法内部,内部方法中的return语句仅从内部方法本身退出,然后外部方法继续执行。同样的规则适用于在lambda内部定义lambda、在方法内部定义lambda或在lambda内部定义方法的情况。然而,当一个proc在方法内部被定义时,return语句将会从proc以及外部(封闭)方法中退出。例如:
def meditate
puts "Adjusting posture…"
p = Proc.new { puts "Ringing bell…"; return }
p.call
puts "Sitting still…"
end
meditate
Output:
Adjusting posture…
Ringing bell…
请注意,由于过程(proc)内部的返回语句已经退出了过程(proc)和包含它的方法,所以方法的最后一行没有被执行。
如果我们定义一个没有外部方法(enclosing(outer) method)并使用返回(return)语句的过程(proc),它将会抛出一个LocalJumpError。
p = Proc.new { puts "Ringing bell…"
p.call
Output:
Ringing bell…
LocalJumpError: unexpected return
这是因为当在一个过程中遇到返回语句时,它会从该过程被定义的范围中返回,而不是从调用该过程的上下文中返回。在以下示例中,由于该过程试图从顶层环境(即它所在的定义位置)返回,导致出现了LocalJumpError异常。
def meditate p
puts "Adjusting posture…"
p.call
puts "Sitting still…"
end
p = Proc.new { puts "Ringing bell…"; return }
meditate p
Output:
Adjusting posture…
Ringing bell…
LocalJumpError: unexpected return
通常,在proc中使用return语句并不是一个好主意。Procs通常在方法之间传递,如果定义proc的方法已经返回,它将抛出异常。在下面的示例中,我们可以删除return语句。但是,有些情况下我们确实需要返回一些东西。在这种情况下,最好使用lambda而不是proc。我们将在后面看到,lambda以一种不同的方式处理return语句,更像方法。
以下是涉及return语句的另一种情况:
def zafu_factory
Proc.new { puts "Round black zafu"; return }
end
def meditate
puts "Adjusting posture…"
p = zafu_factory
p.call
puts "Sitting still…"
end
meditate
Output:
Adjusting posture…
Round black zafu
LocalJumpError: unexpected return
发生了什么?zafu_factory方法创建并隐式返回了一个proc。然后,meditate方法调用了该proc,当proc中的return语句被执行时,它试图从定义它的上下文(即zafu_factory方法)返回。但是,zafu_factory已经返回了proc,并且每次调用方法只能返回一次。换句话说,由于在调用proc时zafu_factory方法已经返回,因此尝试第二次返回时会抛出异常。
请参阅有关
Ruby中的Procs和Lambdas:闭包的博客文章以获取更多信息。
return
语句有关。在过程中使用return
将尝试从调用方法返回。因此,p.call
尝试从test
和procbuilder
返回。 - abhinav