2009-07-05 17 views
2

在Ruby 1.8(我的版本是1.8.7-72),此代码:在里面红宝石为返回拉姆达崩溃内环1.8

foo = lambda do 
    for j in 1..2 
    return 
    end 
end 
foo.call 

崩溃了LocalJumpError

test2.rb:3: unexpected return (LocalJumpError) 
    from test2.rb:2:in `each' 
    from test2.rb:2 
    from test2.rb:6:in `call' 
    from test2.rb:6 

为什么它是否这样做?但是,它似乎在我的Ruby 1.9版本上运行良好。

编辑:它不仅仅是一个拉姆达内的返回;以下运行正常:

foo = lambda do 
    return 
end 
foo.call 

回答

8

发生了什么事是,在拉姆达的中间语句被内部转换成块。在Ruby中,块内的返回语句被限定在它们的封闭方法中。考虑以下几点:

def bar 
    foo = lambda do 
    for j in 1..2 
     return j 
    end 
    end 
    foo[] 
end 
p bar 

当运行bar1返回,因为return的作用域是整个bar方法。要从块返回,您需要使用nextbreak,它们都需要参数。考虑:

def bar 
    foo = lambda do 
    for j in 1..2 
     break j 
    end 
    end 
    foo[] + 1 
end 
p bar 

此中断返回您从该块,并阻止任何后续迭代。在这种情况下,调用bar将返回2,因为迭代器将返回1,因此foo[] + 1将返回2

如果所有这些听起来令人困惑,那么要认识到的主要问题是块内返回的范围是周围的方法,如果缺少周围的方法,则会引发LocalJumpError

+0

为什么不能将范围扩展到lambda?我不能简单地跳出循环,因为在我原来的场景中,for循环后面有代码,我需要跳过 – user102008 2009-07-05 07:27:20

+0

您可以尝试使用真实的方法,而不是lambda。 – 2009-07-05 15:17:38

0

可以逃避环和拉姆达与一抛,其余/捕获

foo = lambda do 
     catch(:escape) do 
      for j in 1..2 
      throw :escape 
      end 
      # other code that won't get run 
     end # catch(:escape) 
     end # lambda 

throw也有一个可选的第二个参数,则您可以使用它返回一个值。