Menu

Ciclo while in R: while, repeat e break spiegati

Come funzionano i cicli while in R: il ciclo che controlla prima la condizione, repeat con break come do-while di R, next e le abitudini che ti tengono lontano dai cicli infiniti.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Il ciclo while

Un ciclo while in R continua a eseguire il suo corpo finché una condizione resta TRUE. Mentre un ciclo for viene eseguito una volta per ogni elemento di qualcosa, while viene eseguito un numero di volte sconosciuto, finché una condizione non cambia:

Tre parti fanno funzionare ogni ciclo while, e qui si vedono tutte e tre:

  1. La preparazione prima del ciclo: count <- 1 dà alla condizione qualcosa da verificare.
  2. La condizione: count <= 5, costruita con i soliti operatori di confronto, controllata prima di ogni passaggio.
  3. L'aggiornamento dentro il corpo: count <- count + 1 porta il ciclo verso la fine.

Togli la parte 3 e la condizione resta TRUE per sempre: il ciclo non finisce mai. È il rischio tipico di while, e il resto di questa pagina parla soprattutto di come gestirlo.

La condizione viene controllata prima di ogni passaggio

while verifica prima la condizione, poi esegue il corpo. Ne derivano due conseguenze. Se la condizione è già FALSE all'inizio, il corpo viene eseguito zero volte:

E il controllo avviene tra un passaggio completo e l'altro, non a metà corpo: una volta iniziato, un passaggio arriva fino in fondo anche se la condizione diventa FALSE a metà. Se devi uscire a metà corpo, per questo c'è break (più avanti).

Un esempio pratico: dimezzare finché non si scende sotto una soglia

Il posto naturale di while è il "continua finché": non puoi sapere in anticipo quanti passaggi serviranno, quindi for non va bene. Quante volte puoi dimezzare 1000 prima che scenda sotto 1?

Dieci dimezzamenti, che finiscono a circa 0.977. Lo schema, una variabile di stato che il corpo riduce e un contatore che fa crescere, copre una grande parte dei cicli while reali: metodi numerici che continuano finché l'errore non è abbastanza piccolo, simulazioni che vanno avanti finché una risorsa non si esaurisce, tentativi ripetuti finché una chiamata non riesce.

repeat + break: il do-while di R

R non ha la parola chiave do-while, cioè nessun ciclo che verifica la condizione dopo il corpo. Ha però repeat, che ripete all'infinito senza condizioni, e break, che esce subito da qualsiasi ciclo. Metti il test con break alla fine del corpo di un repeat e hai costruito esattamente un do-while, un ciclo il cui corpo viene eseguito di sicuro almeno una volta:

Il corpo viene sempre eseguito prima del primo test, quindi n viene raddoppiato almeno una volta; il ciclo esce a 128, il primo raddoppio oltre 100. Usa questa forma quando la descrizione onesta è "fai la cosa, poi decidi se rifarla": leggere un input finché non è valido, estrarre campioni finché uno non va bene. Un repeat senza un break raggiungibile è per costruzione un ciclo infinito, quindi scrivi prima il break e poi riempi il corpo.

break funziona allo stesso modo nei cicli while e for: è l'uscita generale del "qui abbiamo finito", e si abbina naturalmente alle istruzioni if che verificano una condizione a metà corpo.

next dentro un ciclo while

next salta il resto del passaggio corrente e torna al controllo della condizione. Funziona in while come in for, ma con un tranello tipico di while: se l'aggiornamento arriva dopo il next, saltarlo significa che la variabile del ciclo non avanza mai, e hai costruito un ciclo infinito. Metti l'aggiornamento prima del next:

Questo stampa i numeri pari da 2 a 10. Sposta i <- i + 1 sotto la riga del next e il primo valore dispari salterebbe l'aggiornamento per sempre. Nei cicli for questo pericolo non esiste (la variabile del ciclo avanza da sola), ed è un motivo in più per preferire for quando devi semplicemente percorrere una sequenza.

Proteggersi dai cicli infiniti

Ogni ciclo infinito è lo stesso bug: niente nel corpo modifica le variabili da cui dipende la condizione, oppure le modifica nella direzione sbagliata. In modo interattivo puoi interrompere con Esc o Ctrl+C, ma in uno script il processo resta semplicemente bloccato. Due abitudini lo evitano.

Primo, quando scrivi la condizione, chiediti subito "quale riga del corpo la porta verso FALSE?" e assicurati che quella riga venga eseguita in ogni percorso possibile nel corpo (attento al tranello del next visto sopra).

Secondo, per i cicli di cui non riesci a dimostrare facilmente la fine, aggiungi un limite massimo di iterazioni, così un errore di logica produce un risultato diagnosticabile invece di una sessione bloccata. Qui protegge un ciclo in stile Collatz, che dimezza i numeri pari e trasforma un x dispari in 3 * x + 1, finché non arriva a 1:

Partendo da 10, il ciclo arriva a 1 in 6 passi. Se qualche valore iniziale non arrivasse mai a 1, la clausola steps < 10000 chiuderebbe comunque il ciclo, e lo stato stampato ti direbbe che qualcosa è andato storto: una risposta sbagliata che puoi vedere è meglio di un programma che non risponde mai. L'operatore && con valutazione a corto circuito è quello giusto qui: entrambi i lati sono valori singoli e il limite si legge come un'unica frase.

while o for: come scegliere

La regola pratica riguarda cosa sai in anticipo:

  • Sai su cosa stai iterando (gli elementi di un vettore, i numeri da 1 a n): usa un ciclo for, la variabile del ciclo si gestisce da sola.
  • Conosci solo la condizione di arresto (finché converge, finché è sotto la soglia, finché è valido): usa while.
  • Il corpo deve essere eseguito almeno una volta prima che qualsiasi test abbia senso: usa repeat con un break di chiusura.

Se ti ritrovi a gestire un contatore manuale in un ciclo while solo per percorrere un vettore, è un ciclo for travestito: cambialo.

Cosa ti porti a casa

  • while (condition) { ... } controlla prima ed esegue poi: una condizione falsa all'inizio significa zero passaggi.
  • Il corpo deve portare la condizione verso FALSE; il trio preparazione / condizione / aggiornamento è tutta la disciplina.
  • R non ha la parola chiave do-while: repeat { body; if (done) break } è l'idioma, e garantisce almeno un passaggio.
  • break esce da qualsiasi ciclo; con next in un while, aggiorna la variabile del ciclo prima del salto, altrimenti non avanza mai.
  • Un limite massimo di iterazioni (&& steps < 10000) trasforma un potenziale blocco in una risposta sbagliata visibile e facile da correggere.

Prossimo passo: i vettori, la struttura dati che ogni ciclo di questa pagina ha percorso, e il motivo per cui molti cicli in R possono sparire del tutto.

Domande frequenti

Come funziona un ciclo while in R?

while (condition) { ... } controlla prima la condizione ed esegue il corpo solo finché resta TRUE. Prima o poi qualcosa nel corpo deve rendere la condizione FALSE, di solito aggiornando un contatore o riducendo un valore, altrimenti il ciclo non finisce mai. Se la condizione è FALSE già all'inizio, il corpo viene eseguito zero volte.

R ha un ciclo do-while?

Non come parola chiave. L'idioma è repeat { ...body...; if (condition) break }: repeat ripete senza condizioni, quindi il corpo viene eseguito di sicuro almeno una volta, e il break alla fine fa da test di uscita del do-while.

Come si ferma un ciclo infinito in R?

In modo interattivo, premi Esc (RStudio) o Ctrl+C (terminale) per interromperlo. Per evitarlo fin dall'inizio: assicurati che il corpo aggiorni a ogni passaggio le variabili della condizione e aggiungi un limite massimo di iterazioni, while (working && steps < 10000), così un errore di logica produce un conteggio sbagliato invece di una sessione bloccata.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA