Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Pedro Rolo

Min Read

21 février 2024

Présentation du langage de programmation Elm

J'ai jeté un œil au langage de programmation Elm et au framework Elm. Il s'agit d'une approche de programmation fonctionnelle typée du frontend qui influence d'autres technologies populaires d'une manière quelque peu perturbatrice. Cet article est un compte rendu de ce que j'ai découvert à propos d'Elm.

Cet article sera divisé en deux parties. Dans cette première partie, je vais me concentrer sur les fonctionnalités qui font d'Elm une alternative intéressante à Javascript.

Dans la deuxième partie, je me concentrerai sur la perspective historique qui fait qu'Elm vaut le détour ; je développerai les deux caractéristiques principales du langage : la pureté fonctionnelle et le typage statique ; et enfin, je regarderai qui utilise Elm dans le monde réel.

blue arrow to the left
Imaginary Cloud logo

Qu'est-ce que Elm ?

Elm est un framework et un langage de programmation fonctionnel typé destinés au développement frontal. Il s'inspire d'un langage de programmation appelé Haskell pour améliorer la maintenabilité de Javascript, tout en restant aussi simple et proche de Javascript que possible. L'architecture du framework est similaire à Redux, qui a d'ailleurs été fortement inspiré d'Elm.

blue arrow to the left
Imaginary Cloud logo

1. Elm est facile

Oubliez ce que vous avez entendu à propos de la programmation fonctionnelle. Des mots fantaisistes, des idées bizarres, un mauvais outillage.
— Evan Czaplicki, créateur d'Elm

Lors de la conception du langage, l'auteur d'Elm a choisi de placer l'utilisateur au centre de ses choix de conception. Si vous jetez un œil à son »Soyons mainstream«, vous remarquerez que l'accent est mis sur qui est l'utilisateur (le programmeur Javascript) et de quoi il a besoin, en utilisant ce que l'on appelle Conception axée sur l'utilisation. Cette philosophie réduit les caractéristiques du langage à l'essentiel et facilite son apprentissage.

Messages d'erreur conviviaux

[Un] concepteur de logiciels récemment embauché avait étalé les listes de sources sur la table de conférence et avait soigneusement passé un cristal suspendu à une longue chaîne sur le code source. De temps en temps, le designer a marqué un cercle en rouge sur la liste. Plus tard, un de mes collègues a demandé au designer ce qu'il avait fait dans la salle de conférence. La réponse nonchalante : « Trouver les bugs de mon programme ».
C'est une histoire vraie, elle s'est produite au milieu des années 1980, lorsque les gens espéraient vivement trouver des pouvoirs cachés dans les cristaux.
— MIT Press,
Présentation des algorithmes, Dix-huitième impression (1997)

Les messages d'erreur d'Elm sont extrêmement sympathiques. D'une part, cela provient du système de types statiques, qui permet au compilateur de connaître et d'indiquer clairement les différences entre les types de valeurs attendues et celles fournies à nos fonctions. D'autre part, comme il n'existe pas de classes de types, le type d'information affiché dans les messages d'erreur est très réaliste :


Outre cette clarté atypique, le concepteur du langage a décidé que les messages d'erreur devaient être prioritaires. Ainsi, en plus d'indiquer formellement ce qui ne va pas dans les programmes, le compilateur fournit également des « conseils » sur les intentions du programmeur et propose des suggestions de solutions possibles, par exemple :


Aucune classe de type

[Haskell ne sert à rien.]
Simon Peyton Jones, Contributeur majeur à la conception du langage de programmation Haskell.

C'est vrai, ce n'est pas Haskell - La principale source d'inspiration d'Elm. Tout en suivant le processus de conception axé sur l'utilisation, de nombreuses fonctionnalités de Haskell n'étaient pas nécessaires et n'ont donc pas été ajoutées au langage. Parmi ceux-ci se trouvait le tristement célèbre système de classes de types.

Ce système apporterait tout le vocabulaire mathématique prétentieux que l'on entend généralement chez les programmeurs Haskell et rendrait Elm totalement inapproprié pour le « Joe normal ».

Mais n'avons-nous pas besoin de classes de caractères ? Ils doivent servir à n'importe quel but ! Pourquoi Haskell en a-t-il besoin et pas Elm ? - Eh bien, la réponse repose sur le domaine problématique abordé par chacun de ces langages : alors que Haskell est un langage de programmation polyvalent, Elm ne l'est pas. D'une part, Elm est simplement un langage de programmation frontal capable d'accomplir cette tâche sans avoir recours à une telle complexité. D'autre part, une partie de ce que cette complexité vise à traiter est gérée et cachée dans le runtime Elm, qui gère les effets secondaires et les mutations d'une manière spécifique au domaine.

blue arrow to the left
Imaginary Cloud logo

2. Elm est en sécurité

Nous n'avons eu aucun échec d'exécution [...]. Nous avons également eu moins de bugs, en grande partie parce que le système de types d'Elm vous oblige à modéliser votre domaine avec plus de soin. [...] Pour résumer, notre responsable a mandaté que tout nouveau code soit écrit en Elm.
— Jeff Schomay, spécialiste du front-end chez Pivotal Tracker

Le système de type Elm est très sûr et sa conception a deux conséquences qui méritent d'être remarquées :

  • Il n'y a aucune erreur d'exécution
  • Il n'y a pas de valeurs nulles
  • Les déclarations de contrôle sont obligées de faire face à toutes les possibilités

Aucune erreur d'exécution

Mon objectif était de m'assurer que toute utilisation de références devait être absolument sûre, avec une vérification effectuée automatiquement par le compilateur. Mais je n'ai pas pu résister à la tentation [...]
— Tony Hoare, inventeur de la référence nulle

Alors que d'autres langages de programmation gèrent les erreurs en tant que partie du langage avec des fonctionnalités très spécifiques, généralement appelées exceptions ou erreurs, Elm ne propose aucune primitive spécifique pour déclencher des erreurs ou les gérer. La possibilité d'échec est plutôt modélisée à travers les types de valeurs renvoyées et gérées par les fonctions. Certains types paramétriques peuvent être utilisés pour transmettre des informations sur les défaillances, tels que les types Peut-être; Résultat et Tâche.

Le Peut-être type est le plus simple d'entre eux. Il est défini comme suit :

Le un dans cette expression peut être remplacé par n'importe quel type spécifique, par exemple une valeur de type Peut-être String peut soit prendre une valeur telle que Juste « une chaîne spécifique » ou Rien.

Ainsi, une fonction renvoyant une valeur de - par exemple - Peut-être String peut renvoyer une valeur Juste « Je suis la chaîne renvoyée » en cas de réussite ou de retour Rien en cas d'échec. Par la suite, le programmeur est toujours obligé de choisir quoi faire dans les deux cas et le langage ne permet pas au programme de compiler si les deux possibilités ne sont pas gérées.

Pas de valeur nulle

C'est grâce à l'approche présentée précédemment que le langage évite d'avoir une valeur nulle. Et débarrassez-vous ainsi de tous ces habituels undefined n'est pas une fonction erreurs. En cas d'échec, le type transmettra explicitement ces informations et le compilateur forcera le programmeur à traiter ce cas.

Toutes les possibilités doivent être prises en compte

Comme Elm est un langage purement fonctionnel, le but de l'évaluation d'un élément est d'en tirer une valeur. Ainsi, Elm oblige le développeur à fournir une valeur de retour pour chaque instruction de contrôle. Cela implique que chaque si la déclaration a besoin d'un autre clause et cas les instructions doivent gérer toutes les valeurs d'entrée possibles.

Par exemple, examinons un type de données abstrait Discipline typographique qui pourrait prendre comme valeur Statique; Dynamique ou Graduelle:


et si nous gérons une valeur de ce type comme entrée d'une instruction case (une instruction switch), mais oublions de gérer l'une des possibilités :


le compilateur compile le programme :


Ainsi, lorsque nous modifions nos types pour ajouter plus de fonctionnalités, le compilateur nous avertit qu'il y a du code à ajouter pour gérer une nouvelle possibilité.

blue arrow to the left
Imaginary Cloud logo

3. Elm est amusant

Tu dois trouver ce que tu aimes.
— Steve Jobs

Elm's boucle de rétroaction courte et syntaxe épurée en font un environnement de travail très agréable. Voyons comment ces éléments contribuent à la joie des développeurs d'Elm.

Boucle de rétroaction courte

Évitez le succès à tout prix.
Simon Peyton Jones, Contributeur majeur à la conception du langage de programmation Haskell.

Une conséquence intéressante des caractéristiques de sécurité décrites précédemment est la façon dont elles raccourcissent la boucle de rétroaction. L'activité de programmation consiste généralement à répéter les activités suivantes :

  • Réflexion - réflexion sur le code à écrire
  • Saisie : saisie du code
  • Compilation - corrigez le code pour qu'il se compile
  • Testing - testez si le code fait ce qu'il était censé faire

La dernière étape est souvent celle où les développeurs passent le plus de temps, et ce temps est soit consacré à l'écriture de tests automatisés, soit à l'interaction avec le programme pour confirmer qu'il est correct. La plupart des programmeurs diraient que cette phase est la moins joyeuse.

La sécurité d'Elm et l'absence d'exceptions d'exécution transfèrent une partie du Tests échelonner les efforts dans le Compiler phase. Lorsqu'il utilise Elm, le programmeur passe un peu plus de temps à la phase de compilation - à interagir avec le compilateur jusqu'à ce que le programme soit considéré comme correct - et beaucoup moins de temps à la phase de test, lorsque la seule chose qui peut échouer est de savoir si les exigences métier sont satisfaites - et non si le programme plante ou non.

En utilisant Elm, le programmeur sera informé plus tôt de ses erreurs, sans avoir à passer autant de temps pendant la longue phase de test.

Syntaxe épurée

La syntaxe d'Elm est inspirée de Haskell et minimaliste. Il n'y a que deux instructions de contrôle et très peu de mots réservés.

Le centre de cette syntaxe est la fonction. Si la caractéristique syntaxique la plus utilisée de tout langage de programmation structuré est l'invocation de fonctions, alors pourquoi la plupart des langages de style Algol ont-ils recours à autant de caractères spéciaux pour l'invocation et la définition des fonctions ?


Pour écrire la définition et l'invocation ci-dessus, nous avons dû taper 8 caractères spéciaux pour la définition de la fonction :

et 4 sur l'invocation de la fonction :

En fonction de la langue de votre clavier, le nombre de touches de modification enfoncées ; les désagréments et les blessures prématurées dues à des entorses répétitives peuvent varier.

Elm nettoie ça. Si la fonction est si importante, elle doit être facilement saisie et modifiée :


Comme vous pouvez le constater, cette définition de fonction ne nécessite aucun caractère spécial. Les signatures de type sont facultatives et déduites automatiquement par le compilateur, ce qui nous permet d'expérimenter rapidement sans avoir à les saisir explicitement. Ils sont néanmoins utiles : il est parfois utile d'avoir la signature typographique comme guide lors de l'écriture d'un morceau de code moins évident, et ils constituent souvent une forme de documentation utile. Ainsi, dans Elm, les signatures de type sont (éventuellement) écrites sur une ligne séparée (certains éditeurs généreront automatiquement la signature de type lorsque nous la demanderons !) :


Une autre caractéristique qui rend le langage assez amusant à utiliser est que chaque fonction est sélectionnée et peut donc être appliquée à un sous-ensemble de ses arguments, renvoyant une fonction dite partiellement appliquée qui n'attend que les arguments manquants. Ainsi, le code suivant :


correspond au code Javascript suivant :


Le principal avantage de cette fonctionnalité est que le code utilisant des fonctions d'ordre supérieur devient très propre :


Cependant, si nous enchaînons ces opérations, nous commençons à obtenir une mer de parents imbriqués, typique d'un Lisp:


Pour éviter ce problème, le langage fournit les opérateurs de tuyauterie (<| et |>). Ils permettent de chaîner les applications de fonctions avec une syntaxe similaire à celle de faire passer un argument dans un pipeline de transformations :


De la même manière ; vous pouvez également utiliser la composition (<<) ou composition inversée (>>) opérateurs pour exprimer la même chose sans avoir à faire explicitement référence à l'argument en cours de thread :


Cette syntaxe succincte et pratique, ainsi que les jolis messages d'erreur, font d'Elm un outil idéal pour les expériences interactives, à la fois en utilisant le REPL et en utilisant le compilateur.

Joli outillage

Lorsque vous démarrez un projet Elm, vous bénéficiez immédiatement de nombreuses fonctionnalités prêtes à l'emploi :

  • Un framework de rendu basé sur un Dom virtuel (comme Réagir)
  • Un conteneur d'état (comme Redux)
  • L'immuabilité qui, dans JS, est généralement obtenue en utilisant Immutable fait partie de la définition du langage Elm.
  • Vérification de type - similaire - mais plus puissante - à celle que vous pouvez obtenir en utilisant Flux
  • Un environnement de développement interactif similaire à celui fourni par Webpack, appelé Réacteur Elm
  • Un gestionnaire de paquets appelé elm-package

Et cela vaut la peine de développer d'autres outils :

Débogueur qui voyage dans le temps

C'est l'une des choses que Redux a obtenues en implémentant l'architecture Elm. Lors du développement et de l'essai d'un programme, nous sommes en mesure d'inspecter les actions effectuées sur cette interface et de faire des allers-retours dans le temps afin d'analyser l'état du programme à chaque moment de son exécution.

Dans Redux, cette fonctionnalité est assez fragile en raison de la nature impérative de Javascript, et pour y faire face, il est nécessaire d'utiliser Immuable ou une autre bibliothèque pour éviter de modifier directement l'état de l'application. Dans Elm, ce problème n'existe tout simplement pas, car il n'existe pas de mutation au niveau de la langue. La conception du langage elle-même nous protège de ce type de problèmes et de la nécessité d'utiliser des bibliothèques supplémentaires.

Rédacteurs en ligne

De plus, vous pouvez modifier la langue directement sur le navigateur Web, sans avoir à installer quoi que ce soit. Voici un bon exemple de site proposant des fonctionnalités d'édition en direct :

  • Ellie, idéal pour expérimenter avec plus d'un fichier et permettre l'utilisation de packages supplémentaires qui n'appartiennent pas au cœur du langage.

Version sémantique appliquée automatiquement

Lors de la publication d'une nouvelle version du package, l'outil Elm vérifie si les fonctions exportées par nos modules :

  • ont changé leurs signatures ;
  • uniquement les nouvelles fonctions exportées ;
  • ou n'a pas modifié les signatures des fonctions exportées.

Selon chacune de ces possibilités, la modification sera répercutée sur le numéro de version du package calculé automatiquement, ce qui permettra de savoir s'il s'agit de modifications majeures, de modifications mineures ou de corrections de bugs ; et s'il est possible de mettre à niveau la version d'une bibliothèque utilisée en toute sécurité.

blue arrow to the left
Imaginary Cloud logo

À suivre

Dans la partie 2 - disponible ici - Je vais expliquer pourquoi le typage statique et la pureté fonctionnelle sont liés aux tendances actuelles de l'écosystème Javascript. Je parlerai également de qui utilise Elm et de sa maturité. Restez à l'affût, car j'écrirai à ce sujet la semaine prochaine.

À Imaginary Cloud nous disposons d'une équipe d'experts en développement de logiciels. Si vous pensez avoir besoin d'aide pour votre projet numérique, écrivez-nous ici!

Ready for a UX Audit? Book a free call

Vous avez trouvé cet article utile ? Ceux-ci vous plairont peut-être aussi !

blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
Pedro Rolo
Pedro Rolo

Développeur de rails avec plus de 10 ans d'expérience dans diverses technologies. Je m'intéresse à la programmation fonctionnelle.

Read more posts by this author

People who read this post, also found these interesting:

arrow left
arrow to the right
Dropdown caret icon