Il flusso di controllo
Scegli con if, ripeti con for o while.
Il flusso di controllo è l’ordine in cui vengono eseguite le istruzioni. Heroes offre if per scegliere quali eseguire, for per percorrere una sequenza e while per ripetere un blocco finché una condizione è vera.
if, e solo bool
Una condizione deve avere tipo bool, quindi valere true o false. Numeri e stringhe non vengono convertiti automaticamente in condizioni:
$ heroes check loops.hero
error[not_bool]: an `if` condition must be `bool`, found `i64` — there is no truthiness in this language
at loops.hero:13:12
|
13 | if x
| ^
Usa if, else if ed else per definire i rami. La condizione non richiede parentesi; il rientro delimita il corpo. if è anche un’espressione, cioè può produrre un valore. Puoi quindi usarlo per scegliere un valore senza assegnarlo separatamente nei due rami.
for x in xs: percorrere una sequenza
# The largest element. Fails on nothing: an empty array has no largest, so
# the caller is asked for a floor instead.
function largest_or(xs: [i64], floor: i64) -> i64
best: i64 @= floor
for x in xs
if x > best
best @ x
return best
Il ciclo visita un elemento alla volta. A ogni iterazione la variabile contiene una nuova copia dell’elemento, senza un indice o un contatore da aggiornare.
Il prossimo capitolo spiega i simboli @= e @. Qui best: i64 @= floor dichiara una variabile modificabile e best @ x le assegna un nuovo valore. Un nome definito con = non può essere riassegnato.
Uscire prima: break
# Sums until the running total would pass a limit, then stops.
function sum_until(xs: [i64], limit: i64) -> i64
total: i64 @= 0
for x in xs
if total + x > limit
break
total @ total + x
return total
Saltarne uno: continue
# Counts the even ones, and shows `continue` earning its keep.
function even_count(xs: [i64]) -> i64
seen: i64 @= 0
for x in xs
if x % 2 != 0
continue
seen @ seen + 1
return seen
break termina il ciclo più interno; continue passa alla sua iterazione successiva. Non puoi indicare un ciclo esterno con un’etichetta. Se devi uscire da più cicli, puoi spostarli in una funzione e usare return per terminarla.
while: ripetere su una condizione
# The conditional loop, with the counter visible: `while cond` has no header
# that hides where the index changes.
function digits_in(n: i64) -> i64
left: i64 @= n
digits: i64 @= 1
while left >= 10
left @ left / 10
digits @ digits + 1
return digits
Un while controlla la condizione prima di ogni iterazione. L’eventuale aggiornamento del contatore si scrive nel corpo, nell’ordine in cui deve essere eseguito.
Contare: un intervallo è una chiamata di funzione
# The loop variable is not needed, so it is `_` — the same wildcard a pattern
# uses, and the reason an unused name is never an accident here.
function repeat_dash(times: i64) -> str
out: str @= ""
for _ in range(from: 0, to: times)
out @ out + "-"
return out
range restituisce una lista di numeri: include from ed esclude to. Devi nominare entrambi gli argomenti perché hanno lo stesso tipo, i64, come spiegato nel capitolo 3.
Usa _ come variabile del ciclo quando non ti serve il valore dell’elemento. Come in un match, _ scarta il valore senza dichiarare un nome. Non può quindi produrre un errore per un nome inutilizzato.
Tutto quanto, in esecuzione
function main()
print(repeat_dash(20))
print("digits in 2026: ", digits_in(2026))
$ heroes run examples/gallery/04-loops.hero
--------------------
digits in 2026: 4
Aggiungere testo a una stringa dentro un ciclo copia ogni volta l’intera stringa, con un costo che cresce a ogni iterazione. Per stringhe lunghe usa repeat o join, che costruiscono il risultato in una sola passata. Il capitolo sulle stringhe spiega la differenza.
Poi: Nomi e modifiche, dove
impari a usare = e @ e a evitare nomi ambigui.
Torna all’elenco dei capitoli.
← Prima: Il fallimento è un valore
Esegui un programma tuo: bastano quattro comandi. Oppure prendi tutto il linguaggio in un file solo, e tutti i programmi già scritti.