L'anatomie d'une fonction
La forme générale d'une fonction Zero :
fun nom(param1: Type1, param2: Type2) -> TypeRetour {
// corps
return valeur
}
Les pièces :
fun— le mot-clé qui introduit une fonction.nom— le nom de la fonction.(param1: Type1, ...)— la liste des paramètres. Chaque paramètre a un type explicite.-> TypeRetour— le type de retour.{ ... }— le corps, un bloc d'instructions.return valeur— sort de la fonction avecvaleur.
Un petit exemple concret :
fun double(value: i32) -> i32 {
return value * 2
}
Voilà toute la fonction. Elle prend un i32, en retourne un autre, et ne fait aucune E/S. À l'intérieur du corps, value est une liaison de style let — utilisable comme n'importe quelle autre locale.
Appeler des fonctions
Les appels ont exactement la tête qu'on attend :
let result = double(21)
L'argument doit correspondre au type du paramètre. Le résultat est lié à result, dont le compilateur infère le type i32 parce que double retourne i32.
Un exemple complet liant une fonction utilitaire et un main — cliquez sur Run pour voir le résultat :
Vous devriez obtenir math works\n sur stdout.
pub et la visibilité
Par défaut, une fonction déclarée dans un fichier est privée à ce fichier (ou à son module — les règles de visibilité se resserrent quand les projets grossissent). Pour exposer une fonction en dehors de son module, préfixez-la avec pub :
pub fun greet() -> String {
return "hello\n"
}
Sans pub, le code d'autres modules ne peut pas appeler greet. Le runtime doit appeler main depuis l'extérieur de tout module défini par l'utilisateur, c'est pourquoi main est toujours pub.
La règle « privée par défaut » est bonne à adopter. Marquez seulement ce que vous voulez exposer comme interface ; le reste reste à l'intérieur du module.
Types de retour
Chaque fonction déclare son type de retour après ->. Types de retour courants :
fun answer() -> i32 { return 42 }
fun ok() -> bool { return true }
fun label() -> String { return "ready\n" }
fun nothing() -> Void { }
Void est le type de retour d'une fonction qui fait son travail à travers des effets de bord plutôt qu'en produisant une valeur. Une fonction Void n'a pas besoin d'un return explicite — arriver à la fin du corps suffit.
fun log(world: World, message: String) -> Void raises {
check world.out.write(message)
}
Appels de fonction qui ignorent une valeur
Si une fonction retourne une valeur dont vous ne vous souciez pas, vous devez quand même reconnaître ce retour. L'idiome est de la lier avec let :
ignored est une liaison que le reste de la fonction ne lit jamais. La convention d'utiliser le nom ignored (ou _) signale que l'abandon est intentionnel. C'est plus de friction qu'un abandon silencieux d'une valeur de retour, et c'est précisément le but : dans un langage où des agents lisent et génèrent du code, une valeur non lue est souvent un bug qu'il vaut mieux faire ressortir.
Le rôle de raises
Une fonction qui peut échouer le déclare sur sa signature. On l'a vu sur main :
pub fun main(world: World) -> Void raises {
check world.out.write("hello\n")
}
La clause raises peut être nue (n'importe quelle erreur) ou précise :
fun validate(ok: Bool) -> i32 raises { InvalidInput } {
if ok == false {
raise InvalidInput
}
return 42
}
raises { InvalidInput } signifie « cette fonction peut échouer avec InvalidInput, et rien d'autre ». Les appelants doivent utiliser check (ou une forme de gestion plus élaborée) pour propager ou traiter l'erreur.
Raises et Check creuse ça en profondeur, y compris ce qui se passe avec plusieurs types d'erreurs et comment check interagit avec la clause raises de l'appelant.
Fonctions génériques
Quand vous voulez qu'une fonction marche pour plus d'un type, déclarez des paramètres de type entre chevrons :
fun makePair<T, U>(left: T, right: U) -> Pair<T, U> {
return Pair { left: left, right: right }
}
T et U sont des paramètres de type — l'appelant décide ce qu'ils sont. Appeler makePair(40, 2_u8) vous donne un Pair<i32, u8>. Voir Generics pour l'histoire complète, y compris les shapes génériques et les contraintes.
Où vivent les fonctions
Dans un petit programme, vous écrivez les fonctions directement dans votre fichier .0. Dans un package, vous répartissez les fonctions dans des fichiers sous src/ et le compilateur résout les références entre fichiers pour vous. Les fondamentaux restent les mêmes — fun, paramètres, type de retour, corps — où que la fonction se trouve physiquement.
Notes de style
Quelques conventions visibles dans les exemples officiels :
- Noms de fonction en minuscules, mots collés (
makePair) ou séparés en camelCase. La bibliothèque standard penche vers le camelCase. - Une seule valeur de retour par fonction. Si vous avez besoin de retourner plusieurs choses, construisez un petit
shapepour elles — c'est plus clair que de retourner un tuple de paire de tuples. - Les fonctions
Voidne font que des appelscheck; les fonctions qui calculent une valeur évitent les E/S quand elles le peuvent. Cette séparation est en partie culturelle et en partie imposée — une fonction de calcul pure ne prend pasworldet donc ne peut littéralement pas faire d'E/S.
Le dernier point mérite qu'on s'y arrête. Comme les E/S vivent derrière la capacité World et que World est passé explicitement, la signature d'une fonction vous dit si elle pourrait faire des E/S. Les fonctions dont les signatures ne mentionnent pas World sont pures vis-à-vis du monde extérieur. C'est une propriété sur laquelle les agents (et les humains) peuvent compter sans lire le corps.
La suite : If/Else
Vous avez vu if apparaître au passage — le prochain document couvre les expressions if/else en détail, y compris la façon dont elles interagissent avec les liaisons et ce qui manque délibérément (pas de coercition vers la vérité, pas de ternaire).
Questions fréquentes
Comment déclarer une fonction en Zero ?
Utilisez fun : fun nom(param: Type) -> TypeRetour { corps }. Ajoutez pub devant pour rendre la fonction visible en dehors de son module. Ajoutez raises après le type de retour si la fonction peut échouer. Par exemple : pub fun double(value: i32) -> i32 { return value * 2 }.
À quoi sert le mot-clé pub ?
pub ?pub marque une déclaration comme publique — visible par du code en dehors de son module actuel. Sans pub, une fonction est privée au fichier (ou au package) dans lequel elle est déclarée. Le point d'entrée conventionnel pub fun main doit être public pour que le runtime puisse le trouver et l'appeler.
Comment retourner une valeur d'une fonction en Zero ?
Écrivez return valeur dans le corps de la fonction. L'expression doit correspondre au type de retour déclaré. Une fonction de type de retour Void ne retourne rien et n'a pas besoin d'instruction return explicite — arriver à la fin du corps suffit.
Les fonctions Zero peuvent-elles prendre plusieurs paramètres ?
Oui. Listez-les entre parenthèses, séparés par des virgules, chacun avec son nom et son type : fun add(a: i32, b: i32) -> i32 { return a + b }. Chaque paramètre est une liaison de style let dans le corps de la fonction. Zero exige des types explicites sur les paramètres — il n'y a pas d'inférence de type des paramètres lors des déclarations de fonction.
Que signifie raises sur une signature de fonction ?
raises sur une signature de fonction ?raises déclare que la fonction peut échouer. Un raises nu autorise n'importe quel type d'erreur ; raises { InvalidInput } restreint à une erreur nommée précise. Les appelants doivent utiliser check (ou une autre construction de gestion de fallibilité) pour reconnaître la possibilité d'échec — ils ne peuvent pas l'ignorer silencieusement.