Dichiarare un enum
enum dichiara un tipo i cui valori sono un insieme fisso di varianti con nome:
enum Status {
ready,
failed,
}
Ora Status è un tipo con esattamente due valori: Status.ready e Status.failed. Nient'altro può essere uno Status.
La grammatica è volutamente minuscola:
enum Name {apre la dichiarazione.- Ogni riga elenca il nome di una variante, separato da una virgola.
}la chiude.
Niente payload, niente valori discriminanti, niente metodi derivati: è questo che mantiene enum "il tipo somma piccolo" di Zero.
Usare un enum
Indichi una variante qualificandola con il tipo dell'enum:
let state: Status = Status.ready
L'annotazione : Status è facoltativa quando il lato destro fissa già il tipo; nella maggior parte dei casi puoi scrivere:
let state = Status.ready
e il compilatore dedurrà che il tipo è Status.
Confrontare valori enum
Due valori enum sono uguali quando sono la stessa variante:
if state == Status.ready {
check world.out.write("ready\n")
} else {
check world.out.write("not ready\n")
}
È il modo più semplice per scegliere un ramo in base a un enum. Per un'analisi esaustiva, cioè per gestire esplicitamente ogni variante, usa match:
match state {
.ready => { check world.out.write("ready\n") }
.failed => { check world.out.write("failed\n") }
}
I vantaggi di match rispetto a if/else if emergono quando più avanti aggiungi una terza variante. Il compilatore ti segnalerà ogni match a cui manca il nuovo caso; una catena if/else finirà in silenzio nel suo ramo predefinito.
Choice e match tratta match più in dettaglio. Funziona sia con enum sia con choice.
Un esempio completo
L'esempio ufficiale di Zero mette enum e choice fianco a fianco nello stesso file:
Status non fa nulla in questo frammento: serve solo a mostrare il contrasto. Una variante di choice associa un payload (value, message) quando viene riconosciuta; una variante di enum non associa nulla perché non c'è nulla da associare.
Enum o choice: un breve albero decisionale
Una regola breve:
- Le varianti sono solo etichette →
enum. - Le varianti devono contenere dati →
choice.
Se stai modellando gli stati di un ciclo di vita e a un certo punto devi associare un messaggio di errore allo stato "failed", cambia il tipo da enum a choice. Ogni variante riceve un tipo di payload e i rami match a valle guadagnano un binding per quel payload. È un refactoring in cui ti guida il compilatore.
In concreto:
// Prima: enum, senza payload
enum Status {
ready,
failed,
}
// Dopo: choice con un payload su ogni variante
choice Status {
ready: Void,
failed: String,
}
Le varianti con payload Void sono semplici etichette in forma di choice. Puoi usare enum e choice per gli stessi stati logici; scegli enum quando davvero non ti servono dati associati.
Casi d'uso
Alcuni esempi quotidiani in cui enum è la risposta giusta:
- Ciclo di vita senza metadati.
Loading,Ready,Empty: stati puri, senza payload. - Modalità.
Read,Write,Appendper la modalità di apertura di un file. - Direzione.
North,South,East,West. - Livello di log.
Trace,Debug,Info,Warn,Error. (Più avanti potresti aggiungere un messaggio, e a quel punto passeresti achoice.) - Giorno della settimana. Un esempio classico.
Ogni volta che useresti una costante intera magica (0 = in attesa, 1 = attivo, 2 = completato), un enum è quasi sempre più chiaro.
Note di stile
- I nomi delle varianti in minuscolo seguono lo stile di Zero per gli identificatori nel resto del linguaggio.
- Una virgola finale dopo l'ultima variante va bene (ed è consigliata per avere diff più puliti: aggiungere una nuova variante non modifica la riga precedente).
- Mantieni corti gli elenchi degli enum. Se hai una dozzina di varianti e molte vorrebbero un payload, probabilmente ti serve una
choice, o una riprogettazione, più che unenumpiù grande.
Prossimo passo: choice e match
Il passo naturale successivo è il cugino più ricco: choice e match, il tipo unione etichettata di Zero e il costrutto di pattern matching che lo accompagna.
Domande frequenti
Cos'è un enum in Zero?
Un enum dichiara un tipo i cui valori sono uno tra un insieme fisso di varianti con nome: etichette senza alcun payload aggiuntivo. Esempio: enum Status { ready, failed }. Un valore di tipo Status è esattamente uno tra Status.ready e Status.failed, e il compilatore lo garantisce.
In cosa enum è diverso da choice?
Le varianti di un enum sono semplici etichette: non contengono dati. Una choice è un'unione etichettata: ogni variante ha un tipo di payload associato, come in choice Result { ok: i32, err: String }. Usa enum quando ti basta distinguere i casi per nome; usa choice quando ogni caso porta informazioni aggiuntive.
Come si controlla quale variante di un enum contiene un valore?
Confronta il valore con la variante: if status == Status.ready { ... }. Per gestire in modo esaustivo tutte le varianti, usa match: il compilatore ti avvisa se dimentichi una variante, ed è il motivo principale per preferire match alle catene if/else if quando il valore è un tipo somma.
In Zero le varianti di un enum possono avere valori associati?
No, a questo serve choice. enum è volutamente il tipo somma minimo: ogni variante è solo un'etichetta. Se devi associare un i32 o una String a una delle varianti, enum non ti basta più e ti serve una choice.
Quando conviene usare un enum in Zero?
Usa enum quando un valore deve essere esattamente uno tra un piccolo insieme di stati con nome e quegli stati non portano dati aggiuntivi. Esempi: il giorno della settimana, il colore di un semaforo, uno stato del ciclo di vita senza metadati, un livello di log. Se ti accorgi di voler associare dati a una delle varianti, passa a choice.