2009-07-05 35 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也有一個可選的第二個參數,則您可以使用它返回一個值。