Menu

Cicli while in Zero: l'iterazione nel linguaggio agent-first

Come funzionano oggi i cicli while in Zero: la condizione, il corpo del ciclo, l'assenza di for e do-while nella prima versione del linguaggio e il legame tra cicli ed effetti espliciti.

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

Le basi

while esegue il suo corpo finché una condizione bool resta true:

while condition {
    // corpo
}

Il compilatore valuta la condizione prima di ogni iterazione:

  • true: esegue il corpo, poi ricontrolla.
  • false: esce dal ciclo.

Un esempio banale tratto dagli esempi di Zero, con una condizione che è già false:

Eseguilo e scatta solo la seconda write. Il corpo del while non viene mai eseguito perché la condizione era false fin dal primo controllo.

La condizione è un bool

Come per if/else, la condizione del ciclo deve essere un bool. Zero non converte interi, stringhe o altri valori in booleani.

while count {              // errore di compilazione
    // ...
}

while count > 0 {          // OK
    // ...
}

La condizione può essere qualsiasi cosa che produca un bool: un binding, un confronto, una combinazione con &&/|| o una chiamata a funzione. Valgono le stesse regole di if.

Cicli con contatore

Il classico schema "fai qualcosa N volte" usa un contatore e un while:

let mut i = 0
while i < 10 {
    // lavoro da fare
    i = i + 1
}

Tre elementi: un valore iniziale, una condizione che confronta con il limite e un aggiornamento nel corpo. È lo schema che ha ogni linguaggio imperativo: Zero semplicemente non lo traveste con una parola chiave for.

Una nota sulla forma mut usata qui sopra: il modo in cui Zero scrive i binding mutabili nella tua toolchain potrebbe essere diverso nelle versioni pre-1.0. Esegui zero check --json su un piccolo test per confermare la sintassi esatta accettata dal tuo compilatore. Lo schema concettuale (contatore + condizione + aggiornamento) è la parte stabile.

Cicli infiniti

Un while la cui condizione è sempre true gira all'infinito:

while true {
    // aspetta del lavoro, gestiscilo, ricomincia
}

È la forma giusta per un ciclo di eventi, un REPL o un server di lunga durata. Per uscire, termini il processo, sollevi un errore dal corpo oppure ristrutturi il codice in modo da rendere falsa la condizione.

Quando usare un ciclo

I cicli sono uno strumento da usare con parsimonia. Cose che in altri linguaggi sembrano cicli spesso in Zero hanno una forma più pulita:

  • Scorrere una collezione fissa: preferisci una funzione offerta dalla libreria standard o dalla tua shape, come una funzione di supporto in stile forEach, un fold o una visita ricorsiva.
  • Leggere fino alla fine dell'input: cicla su una lettura che può fallire, ma usa check e raises per gestire il limite in modo pulito invece di annidare flag di stato.
  • Attendere una condizione con polling: valuta se il design dovrebbe invece consegnarti un segnale. I cicli di polling sono un campanello d'allarme in qualsiasi linguaggio di sistema.

Lo stesso istinto vale per gli agenti: una forma compatta e dichiarativa è più facile da analizzare di un ciclo con contatore scritto a mano, sia per le persone sia per chi genera codice.

Cicli ed effetti

Il corpo di un while, come qualsiasi altro blocco, può fare I/O, ma solo se ha accesso a una capability World (o a una sua parte). Una funzione la cui firma non menziona World può ciclare quanto vuole, ma non può scrivere nulla all'esterno. Questa proprietà vale anche nel corpo del ciclo; il ciclo non concede nuove capability.

Sembra ovvio, ma è il motivo per cui puoi mettere un while in una funzione di calcolo "pura" e sapere comunque, dalla sola firma, che non può stampare nulla né scrivere su disco.

Note di stile

Alcune piccole abitudini che ripagano:

  • Mantieni evidente la condizione. Se la condizione fa un lavoro vero, spostala in una funzione o in un binding con nome, così il ciclo si legge facilmente.
  • Aggiorna il contatore in fondo al corpo, non in punti sparsi. È più facile individuare gli errori di uno.
  • Preferisci condizioni di uscita che puoi esprimere come condizione del ciclo stesso a flag che cambiano a metà iterazione. Meno parti in movimento.

Prossimo passo: shape

Ora hai visto il flusso di controllo di base di Zero. Il prossimo capitolo riguarda la modellazione dei dati, a partire dalle shape, i tipi prodotto di Zero simili alle struct.

Domande frequenti

Come funzionano i cicli while in Zero?

Usa while condition { ... }. La condizione viene valutata prima di ogni iterazione; se è true, il corpo viene eseguito e il ciclo ricontrolla. Se è false, il ciclo termina e l'esecuzione prosegue dopo la parentesi graffa di chiusura. La condizione deve essere un bool.

Zero ha un ciclo for?

La prima versione di Zero offre while come unico costrutto di ciclo. Il linguaggio mantiene di proposito una superficie piccola mentre si stabilizza: meno parole chiave significano meno modi per un agente di scegliere la forma sbagliata. Un for su un intervallo o una collezione potrebbe arrivare più avanti; fino ad allora, costruisci lo stesso schema con while e un contatore.

Come si scrive un ciclo con contatore in Zero?

Inizializza un contatore, esegui un while che lo confronta con il limite e aggiornalo nel corpo: let mut i = 0; while i < 10 { ...; i = i + 1 }. La sintassi della mutabilità è ancora in evoluzione nello Zero pre-1.0, quindi controlla la documentazione attuale per la forma esatta, ma lo schema while + contatore + aggiornamento è l'idioma standard per i cicli con contatore.

Esistono break o continue in Zero?

La maggior parte dei linguaggi della famiglia di Zero offre un costrutto di uscita anticipata dai cicli; la forma esatta nello Zero pre-1.0 è uno degli aspetti che potrebbero cambiare prima della 1.0. L'approccio prudente è strutturare il ciclo in modo che sia la condizione stessa a fare il lavoro, invertendola e aggiornandola perché il ciclo termini in modo naturale, invece di affidarsi a una specifica parola chiave di controllo del flusso.

Un ciclo while in Zero può durare all'infinito?

Sì: while true { ... } è un ciclo infinito. È utile per server, cicli di eventi, REPL e qualsiasi caso senza una condizione di terminazione naturale. A differenza della truthiness implicita, qui true è un letterale di tipo bool, quindi la condizione resta ben tipizzata.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA