Podstawy
while wykonuje swoje ciało, dopóki warunek typu bool pozostaje true:
while condition {
// ciało
}
Kompilator sprawdza warunek przed każdą iteracją:
true: wykonaj ciało, potem sprawdź ponownie.false: zakończ pętlę.
Prosta ilustracja z przykładów Zero, z warunkiem, który od początku jest false:
Po uruchomieniu wykona się tylko drugie write. Ciało while nigdy się nie wykonuje, bo warunek był false już przy pierwszym sprawdzeniu.
Warunek jest typu bool
Tak jak w if/else, warunek pętli musi być typu bool. Zero nie zamienia liczb całkowitych, tekstów ani innych wartości na wartość logiczną.
while count { // błąd kompilacji
// ...
}
while count > 0 { // OK
// ...
}
Warunkiem może być wszystko, co daje w wyniku bool: wiązanie, porównanie, połączenie &&/|| albo wywołanie funkcji. Obowiązują te same zasady co w if.
Pętle z licznikiem
Klasyczny wzorzec "zrób coś N razy" używa licznika i while:
let mut i = 0
while i < 10 {
// praca do wykonania
i = i + 1
}
Trzy elementy: wartość początkowa, warunek porównujący z granicą i aktualizacja w ciele. Ten wzorzec ma każdy język imperatywny; Zero po prostu nie ubiera go w słowo kluczowe for.
Uwaga do zapisu mut powyżej: sposób zapisu mutowalnych wiązań w twoim toolchainie może się różnić w wersjach przed 1.0. Uruchom zero check --json na małym teście, aby potwierdzić dokładną składnię akceptowaną przez twój kompilator. Stała jest idea wzorca (licznik + warunek + aktualizacja).
Pętle nieskończone
while, którego warunek zawsze jest true, działa w nieskończoność:
while true {
// czekaj na zadanie, obsłuż je, powtórz
}
To właściwy kształt dla pętli zdarzeń, REPL-a albo długo działającego serwera. Aby z niej wyjść, kończy się proces, zgłasza błąd z ciała albo przebudowuje kod tak, by warunek przestał być spełniony.
Kiedy sięgać po pętlę
Pętli warto używać oszczędnie. To, co w innych językach wygląda jak pętla, w Zero często ma czytelniejszy kształt:
- Przechodzenie po stałej kolekcji: lepiej użyć funkcji udostępnianej przez bibliotekę standardową albo twój shape, czyli funkcji pomocniczej w stylu
forEach, operacji fold albo rekurencyjnego przejścia. - Czytanie do końca wejścia: zapętl zawodny odczyt, ale granicę obsłuż czysto przez
checkiraises, zamiast zagnieżdżać flagi stanu. - Odpytywanie o warunek: zastanów się, czy projekt nie powinien raczej przekazać ci sygnału. Pętle odpytujące to zły znak w każdym języku systemowym.
Ta sama intuicja dotyczy agentów: zwięzły, deklaratywny kształt łatwiej przeanalizować niż ręcznie pisaną pętlę z licznikiem, zarówno ludziom, jak i generatorom kodu.
Pętle a efekty
Ciało while, jak każdy inny blok, może wykonywać I/O, ale tylko jeśli ma dostęp do capability World (lub jej wycinka). Funkcja, której sygnatura nie wspomina o World, może zapętlać się do woli, ale nie może niczego zapisać na zewnątrz. Ta właściwość obowiązuje także w ciele pętli; pętla nie daje żadnych nowych capabilities.
Brzmi to oczywiście, ale właśnie dzięki temu możesz umieścić while w "czystej" funkcji obliczeniowej i wciąż wiedzieć, na podstawie samej sygnatury, że niczego nie wypisze ani nie zapisze na dysk.
Uwagi o stylu
Kilka drobnych nawyków, które się opłacają:
- Niech warunek będzie oczywisty. Jeśli warunek wykonuje prawdziwą pracę, przenieś ją do nazwanej funkcji lub wiązania, żeby pętla czytała się czysto.
- Aktualizuj licznik na końcu ciała, a nie w wielu miejscach. Łatwiej wtedy wyłapać błędy o jeden.
- Wybieraj warunki wyjścia, które da się wyrazić jako warunek samej pętli, zamiast flag przełączanych w połowie iteracji. Mniej ruchomych części.
Dalej: shape
Znasz już podstawowe sterowanie przepływem w Zero. Następny rozdział dotyczy modelowania danych i zaczyna się od shape, czyli typów produktowych Zero podobnych do struktur.
Najczęściej zadawane pytania
Jak działają pętle while w Zero?
Użyj while condition { ... }. Warunek jest sprawdzany przed każdą iteracją; jeśli jest true, ciało się wykonuje, a pętla sprawdza warunek ponownie. Jeśli jest false, pętla się kończy, a wykonanie przechodzi za nawias zamykający. Warunek musi być typu bool.
Czy Zero ma pętlę for?
Wczesne Zero ma while jako jedyną konstrukcję pętli. Język celowo utrzymuje małą powierzchnię, dopóki się stabilizuje: mniej słów kluczowych to mniej sposobów, by agent wybrał złą formę. for po zakresie lub kolekcji może pojawić się później; do tego czasu ten sam wzorzec buduje się przez while i licznik.
Jak napisać pętlę z licznikiem w Zero?
Zainicjuj licznik, uruchom na nim while i aktualizuj go w ciele: let mut i = 0; while i < 10 { ...; i = i + 1 }. Składnia mutowalności w Zero przed wersją 1.0 wciąż się zmienia, więc dokładny zapis sprawdź w aktualnej dokumentacji, ale wzorzec while + licznik + aktualizacja to standardowy idiom pętli z licznikiem.
Czy w Zero są break i continue?
Większość języków z rodziny Zero ma jakąś konstrukcję wcześniejszego wyjścia z pętli; jej dokładny zapis w Zero przed wersją 1.0 to jeden z obszarów, które mogą się jeszcze zmienić. Ostrożne podejście to taka budowa pętli, żeby całą pracę wykonywał sam warunek (odwróć go i aktualizuj tak, by pętla naturalnie się kończyła), zamiast polegać na konkretnym słowie kluczowym sterującym przepływem.
Czy pętla while w Zero może działać w nieskończoność?
Tak: while true { ... } to pętla nieskończona. Przydaje się w serwerach, pętlach zdarzeń, REPL-ach i wszędzie tam, gdzie nie ma naturalnego warunku zakończenia. W odróżnieniu od niejawnej prawdziwości true jest tu literałem typu bool, więc warunek pozostaje poprawnie typowany.