Heroes / Guida / capitolo 6

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
examples/gallery/04-loops.hero, righe 7–16

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
examples/gallery/04-loops.hero, righe 18–27

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
examples/gallery/04-loops.hero, righe 29–38

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
examples/gallery/04-loops.hero, righe 40–50

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
examples/gallery/04-loops.hero, righe 52–60

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))
examples/gallery/04-loops.hero, righe 70–72
$ 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.