Powiązany artykuł na pewno dobrze mówi o pętlach N + 1/2 Donalda Knutha . Wyrażony w C / C ++ / Java:
for (;;) {
get next element;
if (at the end) break;
process the element;
}
Jest to przydatne do odczytywania wierszy lub znaków z pliku, sprawdzania, czy osiągnięto EOF, a następnie przetwarzania go. Jestem tak przyzwyczajony do tego, for(;;)..if(..)break;
że pojawia się wzór, że jest to dla mnie idiomatyczne. (Zanim przeczytałem artykuł Knutha, przedrukowany w książce Literate Programming , ten kiedyś był „wtf?”.)
Knuth zasugerował słowa kluczowe loop/while/repeat
:
loop:
S;
while C:
T;
repeat
Gdzie S
i T
są symbolami zastępczymi dla serii zer lub więcej instrukcji i C
jest to warunek logiczny. Gdyby nie było S
instrukcji, byłaby to pętla while, a gdyby nie było T
instrukcji, byłaby to pętla do.
Konstrukcję tę można uogólnić, dopuszczając zero lub więcej while C
klauzul, co czyni ją idealną do wyrażania nieskończonych pętli, a następnie niektórych rzadszych warunków, które wymagałyby dwóch kontroli.
W tym samym artykule Knuth zasugerował mechanizm sygnalizacyjny, który byłby lokalną wersją wyjątków rzucania / wyłapywania (jako alternatywa dla używania goto).
Dla mnie? Chciałbym, aby Java wspierała optymalizację połączeń ogonowych, aby w razie potrzeby móc wyrazić dowolną ogólną strukturę sterowania.
Aktualizacja: zapomniałem wspomnieć, że wielu programistów C / C ++ / Java obchodzi ten problem, używając wbudowanego przypisania pod warunkiem while
:
while ((c = getc(f)) != -1) {
T;
}
Używając terminów z konstruktu Knutha, jest to dopuszczalne, gdy S
i C
można je połączyć w jedno wyrażenie. Niektórzy ludzie nienawidzą zobaczyć wbudowanego zadanie wyżej, inni nienawidzą, aby zobaczyć break
w for (;;)
góry. Ale kiedy S
i C
nie można go łączyć, na przykład gdy S
ma wiele instrukcji, for (;;)
jest to jedyna alternatywa bez powtarzania kodu. Inną alternatywą jest po prostu skopiowanie S
kodu:
S;
while (C) {
T;
S;
}
loop/while/repeat
Alternatywa Knutha wydaje się znacznie lepsza.