57
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并且具有不同的输出是由包含显式inbar的事实决定的。fooreturnProc f

有谁知道为什么会这样?

4

3 回答 3

99

Ruby 具有三个结构:

  1. 不是对象,由...{}...do创建end
  2. proc是由or创建的Proc对象。Proc.newproc
  3. lambdaProclambda(或proc在 Ruby 1.8 中)创建的。

Ruby 有三个从某物返回的关键字:

  1. return终止它所在的方法或 lambda。
  2. next终止它所在的块、过程或 lambda。
  3. break终止产生块或调用它所在的proc或lambda的方法。

在 lambdas 中,无论出于何种原因,return其行为都类似于。并以它们的方式命名,因为它们最常与诸如 之类的方法一起使用,其中终止块将导致迭代继续使用集合的下一个元素,而终止将使您跳出循环。nextnextbreakeacheach


如果您return在 的定义中使用foo,您将返回 from foo,即使它在块或 proc 内。要从块中返回,您可以使用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"
于 2009-09-16T22:13:16.030 回答
16

这是Procs 的语义;它不一定是所有块的语义。我同意这有点令人困惑。它的存在是为了增加灵活性(可能部分原因是 Ruby 除了实现之外没有规范)。

行为在Proc实现中定义。Lambdas 的行为不同,因此如果您不希望returns退出封闭方法,请使用lambdas。或者,return从您的Proc.

对 Rubys 闭包的深入研究在这里。这是一个很棒的曝光。

所以:

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) 
于 2009-09-16T23:28:24.833 回答
8

可以这样想:Proc.new 只是创建一个代码块,它是调用函数的一部分。proc/lambda 创建一个具有特殊绑定的匿名函数。一些代码示例将有所帮助:

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 返回并继续下一条语句。

于 2009-09-17T18:29:38.090 回答