Un linguaggio progettato attorno a chi lo legge
La maggior parte dei linguaggi di programmazione è stata progettata per le persone. Le loro grammatiche sono ottimizzate per ciò che conta per un essere umano: sintassi concisa, idiomi espressivi, scorciatoie "eleganti". I compilatori stampano messaggi di errore in prosa perché a leggerli è una persona. Le librerie standard sono organizzate nel modo che i loro autori trovavano facile da ricordare.
Zero parte da una premessa diversa. I suoi lettori principali sono agenti AI: modelli linguistici che scrivono, fanno debug e correggono codice per conto di qualcuno. Le persone restano coinvolte, ma il design del linguaggio tratta gli agenti come utenti di prima classe fin dal primo giorno. Questo singolo cambio di prospettiva si riflette su quasi ogni caratteristica visibile del linguaggio.
Zero è sviluppato da Vercel Labs, ha il suo sito su zerolang.ai ed è open source su github.com/vercel-labs/zero. I file sorgente terminano in .0.
Cinque elementi di questo frammento, cioè pub, World, raises, check e la chiamata esplicita world.out.write, dicono già molto sul modo di ragionare di Zero. Li analizziamo uno per uno qui sotto.
"Tutto è esplicito"
Lo slogan non ufficiale della documentazione di Zero è tutto è esplicito. Il linguaggio evita di proposito quel tipo di meccanismi nascosti che rendono altri linguaggi di sistema comodi per le persone ma insidiosi per chi genera codice:
- Nessun garbage collector obbligatorio.
- Nessun allocatore nascosto.
- Nessun runtime asincrono implicito.
- Nessuna variabile globale magica: niente
stdoutsempre disponibile, nienteprocess.env, niente filesystem implicito.
Tutto ciò che una funzione fa e che tocca il mondo esterno deve comparire nella sua firma. Per una persona significa scrivere parecchio; per un agente che ragiona su cosa fa davvero una funzione, è un regalo.
Capability, non variabili globali
Il modo in cui Zero gestisce l'I/O è l'esempio più chiaro di questa filosofia. Non esiste una funzione print globale. L'output passa da un valore World che il runtime consegna a main:
pub fun main(world: World) -> Void raises {
check world.out.write("ciao\n")
}
Se una funzione in profondità nello stack di chiamate vuole scrivere una riga di log, deve ricevere esplicitamente un World (o una capability più ristretta). Puoi leggere la firma di una funzione e sapere, senza leggerne il corpo, se potrebbe toccare la rete, il filesystem o lo stdout. È il tipo di proprietà su cui può contare un analizzatore statico (o un agente che fa una code review).
La capability World approfondisce questa idea.
Errori espliciti con raises e check
Le funzioni che possono fallire lo dichiarano. Chi chiama funzioni che possono fallire ne prende atto. Non esistono eccezioni silenziose:
raises { InvalidInput } su validate significa "questa funzione può fallire con InvalidInput". check nel punto di chiamata significa "se questo fallisce, propaga l'errore verso l'alto". Non puoi perdere un errore per distrazione: o compare nella firma della tua funzione o il compilatore ti blocca. Leggi Raises e check per tutti i dettagli.
Un compilatore che parla con gli agenti
L'elemento più caratteristico di Zero non è una funzionalità della sintassi, ma l'output del compilatore. Esegui zero check --json su un programma con errori e ottieni qualcosa del genere:
{
"ok": false,
"diagnostics": [
{
"code": "NAM003",
"message": "unknown identifier",
"line": 3,
"repair": { "id": "declare-missing-symbol" }
}
]
}
Tre cose lo distinguono da un normale errore del compilatore:
- Codici di errore stabili.
NAM003oggi significa "identificatore sconosciuto" e significherà esattamente la stessa cosa nella prossima versione del compilatore. Gli agenti possono riconoscere il codice senza interpretare testo in inglese. - Metadati di correzione strutturati. Il campo
repairindica il tipo di correzione che secondo il compilatore risolverebbe l'errore. Un agente può ottenere il piano conzero fix --plan --jsone applicarlo. - Nessuna prosa da interpretare. L'obiettivo è proprio che un agente non debba decifrare un messaggio pensato per le persone per decidere cosa fare dopo.
Diagnostica JSON spiega il formato nel dettaglio.
Una superficie piccola, di proposito
La grammatica di Zero è piccola e regolare, più vicina nello spirito al primo C che a un linguaggio "tutto compreso" come Scala o il C++ moderno. Il motivo è pratico: un agente dovrebbe riuscire ad assimilare l'intero linguaggio durante una sessione senza inciampare nei casi limite.
Questo significa che troverai:
- Un solo modo per dichiarare una funzione (
funopub fun). - Un solo modo per associare un valore locale (
let). - Un solo modo per modellare i tipi prodotto (
shape), uno per i tipi somma (choice) e uno per le enumerazioni semplici (enum). - Un solo costrutto di pattern matching (
match). - Un solo costrutto di ciclo nella prima versione del linguaggio (
while).
Quello che non troverai, almeno in questa fase, sono overloading degli operatori, conversioni implicite, macro, decoratori o tre modi in concorrenza per esprimere la stessa idea. Non è ascetismo: è una scelta deliberata per mantenere la superficie abbastanza piccola da far sì che un agente scelga raramente la variante sbagliata.
Cosa Zero non è
Per chiarire le aspettative:
- Non è un linguaggio di scripting. Zero compila in binari nativi. I programmi sono piccoli (la documentazione parla di eseguibili sotto i 10 KB) e non si portano dietro un runtime.
- Non è Rust, non è Go, non è Zig. La sintassi ha antenati in comune, ma le priorità sono diverse: Rust punta alla sicurezza della memoria con un sistema di tipi sofisticato, Zero punta a essere facile da imparare per un agente con un sistema di tipi volutamente minuscolo.
- Non è stabile. Zero è pre-1.0. Il team è chiaro: arriveranno modifiche incompatibili se servono agli obiettivi agent-first. Non affidarti ancora a Zero per niente di serio.
- Non è una funzionalità della piattaforma di deploy di Vercel. Anche se nasce in Vercel Labs, Zero non è legato a Next.js né all'hosting di Vercel. È un linguaggio di sistema indipendente.
Quando provare Zero oggi
Vale la pena provare Zero oggi se ti interessa:
- Capire come cambia un linguaggio quando i vincoli di design arrivano dagli agenti e non dalle persone.
- Sperimentare l'I/O basato su capability senza adottare un linguaggio di ricerca.
- Vedere come appare un "output strutturato del compilatore" quando è una funzionalità di primo piano e non un ripensamento.
- Dare feedback a Vercel Labs su un progetto in piena evoluzione.
Meglio lasciarlo perdere (per ora) se ti serve un linguaggio stabile per lavoro vero, se cerchi un ecosistema maturo di librerie o se hai bisogno di strumenti multipiattaforma al livello di Rust o Go.
Prossimo passo: installare Zero
La prossima pagina spiega come installare la toolchain di Zero e compilare il tuo primo programma. Dall'inizio alla fine ci vuole circa un minuto.
Domande frequenti
Cos'è il linguaggio di programmazione Zero?
Zero è un linguaggio sperimentale di programmazione di sistema creato da Vercel Labs, pensato perché gli agenti AI siano utenti principali accanto alle persone. Ha una sintassi piccola e regolare, effetti espliciti tramite una capability World e un compilatore che emette diagnostica JSON strutturata e piani di correzione leggibili dalle macchine, che gli agenti possono applicare direttamente.
Chi sviluppa Zero ed è un prodotto ufficiale di Vercel?
Zero nasce in Vercel Labs, il ramo di ricerca di Vercel. È un esperimento aperto ospitato su github.com/vercel-labs/zero, non un prodotto stabile di Vercel. Il README lo definisce esplicitamente pre-1.0 e sconsiglia di usarlo in produzione o con dati sensibili.
Zero è un linguaggio per agenti?
Sì. Lo scopo di Zero è progettare un linguaggio in cui gli agenti AI, non solo le persone, possano leggere, generare, fare debug e correggere codice in modo affidabile. Questo influenza tutto, dalla grammatica piccola e regolare fino all'output JSON del compilatore e ai codici di errore stabili come NAM003.
Com'è fatto un file sorgente di Zero?
I file sorgente usano l'estensione .0. Un programma minimo è così: pub fun main(world: World) -> Void raises { check world.out.write("ciao\n") }. Il parametro World è l'oggetto capability che usi per l'I/O, mentre raises e check rendono esplicite le operazioni che possono fallire.
Zero è pronto per la produzione?
No. Zero è pre-1.0 e dichiaratamente sperimentale. Il compilatore, la libreria standard e la sintassi stanno ancora cambiando. Il team consiglia di eseguirlo solo in ambienti isolati: usalo per imparare, prototipare e dare feedback, non per rilasciare software destinato ai clienti.