Jak mogę wcześniej zwrócić coś z bloku?

91

Gdybym chciał zrobić coś takiego:

collection.each do |i|
   return nil if i == 3

   ..many lines of code here..
end

Jak uzyskać taki efekt? Wiem, że mógłbym po prostu zawinąć wszystko wewnątrz bloku w duże wyrażenie if, ale chciałbym uniknąć zagnieżdżania, jeśli to możliwe.

Break nie zadziała tutaj, ponieważ nie chcę przerywać iteracji pozostałych elementów.

ryeguy
źródło

Odpowiedzi:

177

nextwewnątrz bloku wraca z bloku. breakwewnątrz bloku powraca z funkcji, która oddała blok. Na eachten oznacza, że breakwyjście z pętli i nextprzeskakuje do następnej iteracji pętli (stąd nazwy). Możesz zwracać wartości za pomocą next valuei break value.

sepp2k
źródło
54
+1 dla next valuei break value. Dokładnie to, czego szukałem.
Joshua Pinter
1
break valuenie działało dla mnie, ale next valuedziałało dobrze. Wielkie dzięki.
Francesco Belladonna
4
Nie jestem pewien, czy twoja definicja next i break jest poprawna. Przynajmniej są mylące. break opuszcza najgłębszą pętlę, next przenosi cię do następnej iteracji. źródło: tutorialspoint.com/ruby/ruby_loops.htm
WattsInABox,
3
@WattsInABox nexti nie breaksą w żaden sposób specyficzne dla konstrukcji zapętlonych, więc artykuł, który łączysz, jest bardzo mylący (ponieważ silnie sugeruje coś przeciwnego). I moje opisy są zdecydowanie poprawna, kiedy nexti breaksą używane wewnątrz bloków (zauważ, że whilei forsą rzadko, jeśli w ogóle, stosowany w Ruby więc 99% zastosowań nexti breaksą w blokach).
sepp2k
Myślę, że masz na myśli niepętlające się bloki. To właśnie jest w tym dezorientujące. Nie zgadzam się też z twoim stwierdzeniem o 99%, ale to inny argument.
WattsInABox,
11
#!/usr/bin/ruby

collection = [1, 2, 3, 4, 5 ]

stopped_at = collection.each do |i|
   break i if i == 3

   puts "Processed #{i}"
end

puts "Stopped at and did not process #{stopped_at}"
JD.
źródło
5

W tym przypadku możesz użyć break, aby wcześniej zakończyć pętlę:

collection.each do |i|
  break if i == 3
  ...many lines
end

... oczywiście przy założeniu, że tak naprawdę nie chcesz zwrócić wartości, po prostu wyrwij się z bloku.

Sniggerfardimungus
źródło
To nie tylko powróci z bloku, ale wróci z każdego. Więc pętla zakończyłaby się, a nie kontynuowała z następną wartością. Nie jestem pewien, czy to jest zamierzone.
wrzesień
4
Możesz użyć wartości z breakw Rubim - break 5spowoduje eachzwrócenie 5.
Chuck
1
Dzięki, ale nie chcę przerywać iteracji.
ryeguy