#!/usr/bin/env catnip
# Types de fonctions : annoter un paramètre callback
print("⇒ Le contrat d'un callback")
# (int) -> int : le callback prend un int, retourne un int
appliquer = (cb: (int) -> int, valeur: int) => {
cb(valeur)
}
double = (x) => { x * 2 }
print("appliquer(double, 21) =", appliquer(double, 21))
print()
print("⇒ L'arité fait partie du contrat")
# Un défaut couvre un paramètre : (x, y = 10) est appelable avec 1 argument
avec_defaut = (x, y=10) => { x + y }
print("appliquer(avec_defaut, 32) =", appliquer(avec_defaut, 32))
# Une variadique accepte toute arité suffisante
somme = (*termes) => { termes[0] + termes[1] + termes[2] }
combiner = (cb: (int, int, int) -> int) => { cb(1, 2, 3) }
print("combiner(somme) =", combiner(somme))
print()
print("⇒ Le retour est vérifié à chaque appel, côté appelant")
# Le contrat promet un int : un callback qui retourne autre chose est
# arrêté au moment où son retour devient observable
menteur = (x) => { "pas un int" }
try {
appliquer(menteur, 1)
} except {
e: TypeError => { print("callback menteur rejeté:", e) }
}
print()
print("⇒ La flèche absorbe à droite")
# (int) -> int | None : une fonction qui retourne int OU None
peut_etre = (cb: (int) -> int | None, v: int) => { cb(v) }
pair_ou_rien = (x) => {
if x % 2 == 0 { x } else { None }
}
print("peut_etre(pair_ou_rien, 4) =", peut_etre(pair_ou_rien, 4))
print("peut_etre(pair_ou_rien, 5) =", peut_etre(pair_ou_rien, 5))
print()
print("⇒ Un callback curryfié : le retour est lui-même une fonction")
curry = (cb: (int) -> (int) -> int) => { cb(20)(22) }
additionneur = (a) => { (b) => { a + b } }
print("curry(additionneur) =", curry(additionneur))