Dlaczego widzę tak wiele konstrukcji (;;)? [Zamknięte]

14

Według mojego sposobu myślenia pętla for służy do iteracji w znanym lub możliwym do określenia zakresie.

String[] names = //something;
for ( int i = 0; i < names.length; i++ ) { //do stuff }

co jest równoważne (określenie zakresu i na bok) do:

String[] names = //something;
int i = 0;
while (i < names.length )
{
   // do stuff
   i++;
}

Innymi słowy, forpętla jest po prostu (bardzo przydatnym) cukrem syntaktycznym dla powszechnie stosowanego whilekonstruktu.

Jednak widzę wiele for(;;)konstrukcji w Internecie, które są funkcjonalnie równoważnewhile(true)

Jakie jest tego uzasadnienie? Dlaczego pętla nieskończona dla jest lepsza niż pętla nieskończona podczas?

// Widziałem nawet podręcznik Java, który w ogóle nie używał pętli while! Prowadząc do takich potwornych konstrukcji, jak:

String input = getInput();
for( ; !inputIsValid(input) ; )
{
   //redo;
}
Chris Cudmore
źródło
Głównym powodem jest preferencja. Czytelność powinna mieć jednak znaczenie przy dokonywaniu wyboru, jednak YMMV.
Aaron McIver,
Dlaczego ktokolwiek wolałby niezręczną konstrukcję?
Chris Cudmore,
10
Możesz zamienić whilei fortutaj, a pytanie się nie zmieni. while(true)i for(;;)znaczy to samo. Oczywiście masz silną preferencję while, inni mogą mieć równie silną preferencję for. Nie można powiedzieć, że jedno jest bardziej poprawne niż drugie.
Caleb,
3
@ Chris, nie wydaje mi się, że jestem for(;;)zagmatwany. Jest to standardowy idiom C, który udokumentujesz w sekcji 3.5 K&R (2e). Rozumiem, że ci się nie podoba; Ci powinni zrozumieć, że inni wolą oczywiście go (jeszcze nigdy byś go zobaczyć). Może być mniej lub bardziej akceptowalny w językach innych niż C; otagowałeś ten język-agnostyk, który tylko zmniejsza prawdopodobieństwo ostatecznej odpowiedzi. Znów głosowałem za zamknięciem, ponieważ Q nie jest konstruktywne; gdybym się obraził, oznaczałbym jako ofensywne zamiast lub oprócz zamknięcia. To wszystko.
Caleb,
1
Osobiście uważam, że jest tu prawdziwa okazja, aby mieć kolejną składnię całkowicie dla nieskończonych pętli: coś w styluwheeeeeeee { ... }
detly

Odpowiedzi:

33

Jest to pozostałość po starych praktykach programistycznych na PDP-11 (tak, powiedziałem stary ). Kiedyś zapisywał pojedynczą instrukcję, która była przydatna do przyspieszenia działania pętli.

Aby uzyskać dodatkowe informacje, zobacz: http://www.flounder.com/exceptions.htm

Edward Robertson
źródło
3
Właśnie tego szukałem. Istnieje prawdziwy, uzasadniony powód, ale nie jest już ważny.
Chris Cudmore,
1
@chris Nnnope, współczesne kompilatory czasami narzekają na użycie stałej w stanie pętli. To nie jest wyłącznie retencja.
Izkata,
Jest w tym coś więcej. Pamiętam pisanie C na początku lat 90-tych na systemach uniksowych i chociaż (prawda) {} nie była opcją. Nie było standardowego typu logicznego, ale kilka systemów uniksowych zdefiniowało swoje własne w plikach nagłówka C. Z pamięci przynajmniej jeden sprzedawca uniksowy zdefiniował PRAWDA jako zero, aby pomóc w przetwarzaniu zwrotów funkcji, ponieważ konwencja polegała na zwracaniu zera po sukcesie, a liczby dodatnie były błędami. Oznaczało to, że podczas gdy (PRAWDA) {} nie był przenośny.
Michael Shaw
1
Nie mogę go teraz znaleźć, ale mógłbym przysiąc, że kilka lat temu Dennis Ritchie napisał post na Usenecie, w którym stwierdził, że to po prostu źle, i używał for(;;)składni jako (ich zdaniem) bardziej bezpośredniego stwierdzenia w zamian nie podano kryteriów wyjścia z pętli.
Jerry Coffin
@Ptolemy: Cóż, na pewno mógłbyś napisać while(1) { }.
Ed S.
10

niektóre kompilatory dają ostrzeżenie (coś w rodzaju wyrażenia warunkowego jest stałe ) podczas używania, while( 1 )ale for( ; ; )nie ma o czym ostrzegać. Programiści chcą kodu bez ostrzeżeń, więc używają opcji for.

stijn
źródło
Niektóre rzeczy, o których ostrzegają kompilatory, są jednak całkowicie poprawne, a nawet (w niektórych szczególnych przypadkach) nieuniknione. Dlatego niektórzy z nas traktują ostrzeżenia jako ostrzeżenia. Jeśli je zignorujesz, możesz oczywiście zatopić się w przeklętych rzeczach i nie widzieć ważnych - ale są pragmy i opcje wyłączania ostrzeżeń, lokalnie lub globalnie. Zasadniczo tak, lepiej nie mieć ostrzeżeń, ale zwykle potrzebuję silniejszego powodu, aby przyjąć gorszy styl kodu. Tutaj nie jest gorzej, tylko inaczej, ale i tak „nieskończone” pętle są rzadkie (lub bardzo zły styl).
Steve314,
5

Jest to nawyk nabyty w programowaniu C, w którym nie ma typu boolowskiego. Chociaż (1) byłoby potencjalnie równoważne, ale For (;;) jest często używane, ponieważ pojawia się w K&R, jeśli dobrze pamiętam. Podejrzewam, że gdzieś tam też był powód sprzętowy.

Inżynier świata
źródło
4
... podejrzewam, że był to powód sprzętowy ...
Aaron McIver,
2
Jak wspomniał Edward Robertson, powodem jest to, że kompilator C na PDP-11 nie zdawał sobie sprawy, że prawda w „while (true)” była stałą czasową kompilacji i dodawałaby dodatkową instrukcję (porównanie) podczas generowania zestawu. Ze względu na ograniczone zasoby dostępne w PDP-11, programiści wykorzystali pętlę for, aby zoptymalizować jedną dodatkową instrukcję z programu.
Jetti,
3

bo (;;) można odczytać jako „na zawsze”, co niektórzy uważają za bardziej naturalne niż „choć prawdziwe”.

Oskar N.
źródło
Chociaż nie jest to pierwotny powód, jest to wtórny powód, dla którego preferencje utknęły długo po tym, jak pierwotny powód stał się przestarzały. Jednak bardzo trudno jest znaleźć dowody na poparcie tego, poza pytaniem o wieloletnie doświadczenie programistów.
DarenW
-2

Wszyscy doświadczeni programiści, o których prosiłem, mogą rozpoznać for(;;)szybciej niż while(true)lub while(1).

Kevin Cline
źródło
2
Każdy programista, który jest cholerny, powinien być w stanie rozpoznać wszystkie trzy natychmiast. Wszystkie trzy są na tyle powszechne, że każdy, kto spędził więcej niż 5 minut czytając kod, widział każdego z nich kilka razy.
cHao 11.11.11
1
Badania wykazały, że doświadczeni programiści mogą pojąć for(;;)14ms szybciej niż while(1):-)
Kevin Cline