Menu

Hello World in Zero: scrivi ed esegui il tuo primo programma .0

Il tuo primo programma in Zero: cosa significa ogni pezzo del classico hello world, come eseguirlo con zero run e perché anche un programma di cinque righe usa già World, raises e check.

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

Scrivere il file

Apri il tuo editor e salva queste cinque righe come hello.0 dove preferisci, oppure clicca semplicemente su Esegui nel blocco qui sotto:

Fatto: questo è un programma Zero completo. Per eseguirlo in locale:

zero run hello.0

Dovresti vedere:

ciao da zero

Se ottieni command not found, torna a Installare Zero e assicurati prima che zero --version funzioni.

Analizzare ogni token

Anche questo programma minuscolo mostra già quasi tutto ciò che rende Zero diverso. Leggiamolo da sinistra a destra.

pub

pub segna una dichiarazione come pubblica, cioè visibile fuori dal suo modulo. Il runtime deve trovare main dall'esterno dello scope del file, quindi main deve essere pub. Una funzione di supporto privata nello stesso file non ne avrebbe bisogno.

fun

fun introduce la dichiarazione di una funzione. Zero usa fun, non fn (Rust), func (Go) o function (JavaScript). Una sola parola chiave, usata sempre allo stesso modo.

main

Il nome convenzionale del punto di ingresso. Quando viene eseguito un target eseguibile di Zero, il runtime cerca pub fun main(world: World) e lo chiama. Puoi dare alle altre funzioni il nome che vuoi, ma per convenzione main è riservato all'ingresso del programma.

(world: World)

L'unico parametro si chiama world ed è di tipo World. Il runtime costruisce un valore World prima di chiamare main e glielo passa. Quel valore porta con sé le capability del programma: accesso a stdout, stdin, filesystem, rete e così via, a seconda di cosa il runtime decide di concedere.

Il nome del parametro lo scegli tu: (w: World) o (io: World) compilerebbero senza problemi. Negli esempi la convenzione è world, e la seguiremo anche noi.

-> Void

Il tipo di ritorno. Void significa che la funzione non restituisce nulla di utile: esiste per i suoi effetti collaterali, non per il suo valore. Molte funzioni che scriverai restituiranno tipi veri come i32 o una shape che hai definito tu.

raises

Un raises semplice (senza un tipo di errore specifico) su main dice "questa funzione può fallire". Per main significa che il programma può terminare con uno stato diverso da zero se un check nel corpo propaga un errore verso l'alto. Vedremo forme più ristrette, per esempio raises { InvalidInput }, in Raises e check.

check world.out.write("ciao da zero\n")

Questa è la riga che fa davvero qualcosa. Tre sotto-parti:

  • world.out: lo stream di output standard, esposto come campo della capability World.
  • .write("ciao da zero\n"): un metodo che scrive una stringa su quello stream. Restituisce un risultato che potrebbe indicare un errore (la scrittura potrebbe fallire, lo stream potrebbe essere chiuso).
  • check: propaga quell'errore verso l'alto, se si verifica. Senza check, il compilatore segnalerebbe che il risultato di write viene scartato in silenzio.

Il \n alla fine è un carattere di nuova riga letterale. Senza di esso l'output non andrebbe a capo e il prompt della tua shell finirebbe sulla stessa riga del messaggio.

Cosa è appena successo

Quando hai eseguito zero run hello.0:

  1. Il compilatore ha analizzato il tuo file e ne ha controllato i tipi.
  2. Ha prodotto un piccolo eseguibile nativo per la tua piattaforma.
  3. Il runtime ha costruito una capability World per il processo corrente.
  4. Ha chiamato main(world).
  5. Il tuo codice ha scritto "ciao da zero\n" sullo stream out di quel world, collegato allo stdout del tuo terminale.
  6. main ha restituito Void, il runtime ha fatto pulizia e il programma è terminato con stato 0.

Non c'è garbage collector, nessuna inizializzazione nascosta del runtime, nessun bootstrap implicito dei moduli. L'intero programma è la funzione che hai scritto, più il codice della libreria standard che ha chiamato.

Prova una piccola modifica

Fai in modo che il programma salvi il messaggio in un binding prima di scriverlo:

Eseguilo di nuovo: stesso output, ma ora hai visto i binding let e hai verificato che le stringhe sono valori di prima classe che puoi passare in giro.

Una variante che fallisce

Cosa succede se dimentichi il check?

pub fun main(world: World) -> Void raises {
    world.out.write("oops\n")
}

zero check hello.0 si rifiuterà di compilarlo. Il risultato di write è un valore che può fallire; ignorarlo è un errore di compilazione. O lo passi a check (propagando l'errore) o lo gestisci in modo esplicito. È la stessa idea dei risultati must_use di Rust, solo che qui vale per ogni chiamata che può fallire.

Prossimo passo: la CLI di Zero

Qui hai usato zero run. La CLI ha un piccolo insieme di comandi che vale la pena conoscere, check, run, build, test, fix, explain, ognuno con una modalità --json strutturata pensata per essere letta dagli agenti.

Domande frequenti

Qual è il programma hello world in Zero?

Il classico hello world di Zero è di cinque righe: pub fun main(world: World) -> Void raises { check world.out.write("ciao da zero\n") }. Salvalo come hello.0 ed esegui zero run hello.0.

Cosa significa pub fun main in Zero?

pub rende pubblica una dichiarazione, cioè visibile fuori dal suo modulo. fun dichiara una funzione. main è il punto di ingresso convenzionale che Zero cerca in un target eseguibile. Insieme, pub fun main dichiara il punto di ingresso pubblico che il runtime chiama all'avvio del programma.

Perché main riceve un parametro World?

Zero non ha I/O globale. Tutto ciò che comunica con il mondo esterno, cioè stdout, stdin, file e rete, passa da capability fornite esplicitamente. Il runtime consegna a main un valore World, e quel valore (o parti di esso) è l'unico modo in cui le funzioni possono fare I/O. Così gli effetti collaterali sono visibili nelle firme delle funzioni.

Cosa fanno raises e check nell'hello world?

raises su main dichiara che la funzione può fallire. check world.out.write(...) chiama una funzione che può fallire e, in caso di errore, lo propaga a chi l'ha chiamata: qui è il runtime, che termina con uno stato diverso da zero. Senza check, il compilatore si rifiuterebbe di compilare la chiamata perché l'errore non sarebbe gestito.

Che estensione di file usa Zero?

I file sorgente di Zero usano l'estensione .0 (la cifra zero, non la lettera O). Un file hello.0 è un file sorgente di Zero. Il compilatore si invoca con comandi come zero check hello.0 e zero run hello.0.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA