2013-07-23 8 views
31

Na czym polega problem z tym kodem Ruby 2.0?Nieoczekiwany zwrot (LocalJumpError)

p (1..8).collect{|denom| 
    (1...denom).collect{|num| 
     r = Rational(num, denom) 
     if r > Rational(1, 3) and r < Rational(1, 2) 
      return 1 
     else 
      return 0 
     end 
    } 
}.flatten 

Błąd jest w block (2 levels) in <main>': unexpected return (LocalJumpError). Chcę utworzyć płaską listę zawierającą n (i pozostałe zera), gdzie n jest liczbą liczb wymiernych o mianownikach poniżej 8, które są między 1/3 i 1/2. (it's a Project Euler problem). Próbuję wrócić z wewnętrznego bloku.

+2

Nie używaj "return" w bloku. Po prostu usuń oba 'return', a twój kod będzie w porządku. – oldergod

Odpowiedz

37

Nie można return wewnątrz bloku w Ruby *. Ostatnia wypowiedź staje się wartością zwracaną, więc można po prostu usunąć sprawozdania powrotne w przypadku:

p (1..8).collect{|denom| 
    (1...denom).collect{|num| 
     r = Rational(num, denom) 
     if r > Rational(1, 3) and r < Rational(1, 2) 
      1 
     else 
      0 
     end 
    } 
}.flatten 

*: Można wewnątrz lambda bloki: lambda { return "foo" }.call # => "foo". Ma to związek z określaniem zakresu i tym, co jest jedną z głównych różnic między blokami lambda i blokami proc. Bloki "normalne", które przechodzą do metod, są bardziej podobne do bloków proc.

+55

Ty * możesz * używać 'return' wewnątrz bloku w Ruby. Wróci z metody otaczającej. W tym przypadku * nie ma * metody załączania, * to jest * dlaczego wystąpił błąd, to * nie *, ponieważ 'return' w bloku jest nielegalne. –

+0

@ JörgWMittag Masz rację, upraszczałem. 'return' zwraca dla najbliższej metody * lub *' lambda' bloku, w którym jesteś. Jeśli nie jesteś w środku, otrzymasz "LocalJumpError". – henrikhodne

+0

@ JörgWMittag dzięki za to wyjaśnienie. Odpowiedź była myląca, a ty ją wyjaśniłeś. Rozumiem teraz, dlaczego ten błąd pojawia się łatwo. –