Czy jest możliwe break
z Groovy .each{Closure}
, czy powinienem zamiast tego używać klasycznej pętli?
143
Nie, nie możesz przerwać „każdego” bez rzucenia wyjątku. Prawdopodobnie chcesz klasycznej pętli, jeśli chcesz, aby przerwa została przerwana w określonych warunkach.
Alternatywnie możesz użyć zamknięcia „find” zamiast each i zwrócić prawdę, gdy zrobiłbyś przerwę.
Ten przykład zostanie przerwany przed przetworzeniem całej listy:
def a = [1, 2, 3, 4, 5, 6, 7]
a.find {
if (it > 5) return true // break
println it // do the stuff that you wanted to before break
return false // keep looping
}
Wydruki
1
2
3
4
5
ale nie drukuje 6 lub 7.
Bardzo łatwo jest również napisać własne metody iteratora z niestandardowym zachowaniem przerwania, które akceptuje zamknięcia:
List.metaClass.eachUntilGreaterThanFive = { closure ->
for ( value in delegate ) {
if ( value > 5 ) break
closure(value)
}
}
def a = [1, 2, 3, 4, 5, 6, 7]
a.eachUntilGreaterThanFive {
println it
}
Drukuje również:
1
2
3
4
5
find
lepsze niżany
- zobacz inną odpowiedź poniżej od @Michal, która działa dla mniedef test = [2] test.findResult{ it * 2 }
zwróci 4 zamiast 2Wymień każdą pętlę na dowolne zamknięcie.
Wynik
źródło
any()
w ten sposób jest nieco mylące, ale z pewnością działa i daje możliwość przerwania lub kontynuowania .Nie, nie możesz zerwać z zamknięciem w Groovy bez rzucenia wyjątku. Nie należy również używać wyjątków dla przepływu sterowania.
Jeśli okaże się, że chcesz wyrwać się z zamknięcia, prawdopodobnie powinieneś najpierw pomyśleć o tym, dlaczego chcesz to zrobić, a nie jak to zrobić. Pierwszą rzeczą do rozważenia może być zastąpienie omawianego zamknięcia jedną z (konceptualnych) funkcji wyższego rzędu Groovy'ego. Poniższy przykład:
staje się
staje się
co również pomaga uzyskać jasność. Znacznie lepiej określa cel twojego kodu.
Potencjalną wadą pokazanych przykładów jest to, że iteracja zatrzymuje się tylko na początku pierwszego przykładu. Jeśli masz wątpliwości dotyczące wydajności, możesz chcieć zatrzymać to od razu.
Jednak w większości przypadków użycia, które obejmują iteracje, można zwykle skorzystać z jednej z metod Groovy'ego: find, grep, collect, inject itp. Zwykle wymagają pewnej „konfiguracji”, a następnie „wiedzą”, jak wykonać iterację za Ciebie, abyś mógł faktycznie uniknąć bezwzględnego zapętlania się, gdy tylko jest to możliwe.
źródło
Używam tylko specjalnego zamknięcia
źródło
(1..10) .each {
jeśli (to <5)
wydrukuj to
jeszcze
return false
źródło
each
, po prostu nie wypisuje wartości większych niż 4.else
Jest zbędne, twój kod zrobiłby to samo bez niego. Możesz również udowodnić,each
że nie zrywa,return false
jeśli umieściszprintln "not breaking"
tuż poelse
i tuż przedreturn false
.Możesz się przedrzeć
RETURN
. Na przykładMi to pasuje!
źródło
any
metodę tablicy, zwracającfalse
. Nie możesz złamaćeach
metody w ten sam sposób.