Présentation de Gleam

Gleam est un langage fonctionnel qui se compile à la machine virtuelle BEAM d’Erlang et, depuis la version 0.5, également en JavaScript exécutable sous Node.js. Cette double cible permet de partager le même code source entre services back‑end BEAM et applications front‑end JavaScript. Le langage se veut « friendly », c’est‑à‑dire qu’il masque la plupart des complexités du runtime Erlang tout en conservant une syntaxe très simple.

Principes de conception

Les variables sont immuables ; toute modification passe par une nouvelle liaison let. Le passage de données s’effectue avec l’opérateur de pipe |>, qui impose que la valeur pipée soit le premier argument de la fonction appelée. Cette contrainte rend le flux de données explicite et évite les appels de méthode implicites. Gleam adopte le même modèle d’erreur que Rust : les fonctions retournent un Result contenant soit la valeur attendue, soit une erreur, ce qui force le développeur à gérer chaque cas.

Patrons de contrôle de flux

Le langage ne propose aucune boucle native. Les itérations sont exprimées via des fonctions d’ordre supérieur (par ex. list.each) ou par récursion. Pour la récursion, Gleam s’appuie sur l’optimisation de tail‑call (TCO) du compilateur BEAM : lorsqu’un appel récursif est en position terminale, le cadre d’exécution est réutilisé, ce qui évite la croissance de la pile. Sur la VM Erlang, la pile n’a pas de taille fixe ; une récursion non optimisée consomme de la mémoire heap jusqu’à ce que le processus soit arrêté, ce qui rend la TCO essentielle pour les algorithmes profonds comme le calcul du PGCD.

pub fn main() {
  let order_number_and_amounts = [
    #(101, 100),
    #(102, 200),
    #(103, 300)
  ]
  
  order_number_and_amounts
  |> list.each(fn(x) {
    let #(order_no, amount) = x
    let order_description = "Order #" <> int.to_string(order_no)
    process.spawn_unlinked(fn() {
      // 101 et 103 réussissent, 102 échoue
      process_order…
    })
  })
}

Typage et interopérabilité

Gleam est statiquement typé. Les types combinent les notions d’enum et de struct de Rust, ce qui rend impossible l’apparition d’états non prévus par le modèle de données. Cette sûreté de type se propage aux deux cibles de compilation : les définitions de type restent identiques en BEAM et en JavaScript, facilitant la cohérence entre services distribués. Comparé à Elixir, qui reste dynamiquement typé malgré l’ajout récent du typage graduel, Gleam offre une garantie de vérification à la compilation, ce qui réduit les erreurs d’exécution liées aux types.

Implications pour le développement système

En s’appuyant sur le modèle d’acteurs de BEAM, Gleam hérite de la capacité du runtime à gérer des milliers de processus légers, à isoler les pannes et à redémarrer automatiquement les travailleurs défaillants. Le code présenté montre l’utilisation de process.spawn_unlinked pour créer des tâches qui ne propagent pas les erreurs au processus parent. Cette approche, combinée à l’absence de boucles et à la TCO, rend Gleam adapté aux services qui exigent une haute disponibilité et une scalabilité horizontale sans recourir à des bibliothèques externes complexes.