Premiers pas avec le langage de programmation Elm

Publié: 2022-03-11

Lorsque le développeur principal d'un projet très intéressant et innovant a suggéré de passer d'AngularJS à Elm, ma première pensée a été : pourquoi ?

Nous avions déjà une application AngularJS bien écrite qui était à l'état solide, bien testée et éprouvée en production. Et Angular 4, étant une mise à niveau digne d'AngularJS, aurait pu être un choix naturel pour la réécriture, tout comme React ou Vue. Elm ressemblait à un étrange langage spécifique à un domaine dont les gens avaient à peine entendu parler.

Langage de programmation Elm

Eh bien, c'était avant que je sache quoi que ce soit sur Elm. Maintenant, avec une certaine expérience, surtout après la transition depuis AngularJS, je pense que je peux donner une réponse à ce "pourquoi".

Dans cet article, nous passerons en revue les avantages et les inconvénients d'Elm et comment certains de ses concepts exotiques répondent parfaitement aux besoins d'un développeur Web front-end. Pour un article sur le langage Elm plus didactique, vous pouvez consulter cet article de blog.

Elm : un langage de programmation purement fonctionnel

Si vous avez l'habitude de programmer en Java ou JavaScript et que vous pensez que c'est la manière naturelle d'écrire du code, apprendre Elm peut être comme tomber dans le terrier du lapin.

La première chose que vous remarquerez est l'étrange syntaxe : pas d'accolades, beaucoup de flèches et de triangles.

Vous apprendrez peut-être à vivre sans accolades, mais comment définir et imbriquer des blocs de code ? Ou, où est la boucle for , ou toute autre boucle, d'ailleurs ? Alors que la portée explicite peut être définie avec un bloc let , il n'y a pas de blocs au sens classique et pas de boucles du tout.

Elm est un langage client Web purement fonctionnel, fortement typé, réactif et événementiel.

Vous pouvez commencer à vous demander si la programmation est même possible de cette façon.

En réalité, ces qualités s'additionnent pour vous donner un incroyable paradigme de programmation et de développement de bons logiciels.

Purement fonctionnel

Vous pourriez penser qu'en utilisant la nouvelle version de Java ou ECMAScript 6, vous pouvez faire de la programmation fonctionnelle. Mais, ce n'est que la surface de celui-ci.

Dans ces langages de programmation, vous avez toujours accès à un arsenal de constructions de langage et à la tentation de recourir aux parties non fonctionnelles de celui-ci. Là où vous remarquez vraiment la différence, c'est quand vous ne pouvez rien faire d'autre que de la programmation fonctionnelle. C'est à ce moment-là que vous commencez à ressentir à quel point la programmation fonctionnelle peut être naturelle.

Dans Elm, presque tout est une fonction. Le nom de l'enregistrement est une fonction, la valeur du type d'union est une fonction - chaque fonction est composée de fonctions partiellement appliquées à ses arguments. Même les opérateurs comme plus (+) et moins (-) sont des fonctions.

Pour déclarer un langage de programmation comme purement fonctionnel, plutôt que l'existence de telles constructions, l'absence de tout le reste est d'une importance primordiale. Ce n'est qu'alors que vous pourrez commencer à penser de manière purement fonctionnelle.

Elm est calqué sur des concepts matures de programmation fonctionnelle et ressemble à d'autres langages fonctionnels comme Haskell et OCaml.

Fortement typé

Si vous programmez en Java ou TypeScript, vous savez ce que cela signifie. Chaque variable doit avoir exactement un type.

Certaines différences existent, bien sûr. Comme avec TypeScript, la déclaration de type est facultative. S'il n'est pas présent, il sera déduit. Mais il n'y a pas de type "tout".

Java prend en charge les types génériques, mais d'une meilleure manière. Les génériques en Java ont été ajoutés ultérieurement, de sorte que les types ne sont pas génériques, sauf indication contraire. Et, pour les utiliser, nous avons besoin de la syntaxe laide <> .

Dans Elm, les types sont génériques sauf indication contraire. Prenons un exemple. Supposons que nous ayons besoin d'une méthode qui prend une liste d'un type particulier et renvoie un nombre. En Java ce serait :

 public static <T> int numFromList(List<T> list){ return list.size(); }

Et, en langue Elm :

 numFromList list = List.length list

Bien que facultatif, je vous suggère fortement de toujours ajouter des déclarations de type. Le compilateur Elm n'autoriserait jamais les opérations sur les mauvais types. Pour un humain, il est beaucoup plus facile de faire une telle erreur, surtout lors de l'apprentissage de la langue. Ainsi, le programme ci-dessus avec des annotations de type serait :

 numFromList: List a -> Int numFromList list = List.length list

Il peut sembler inhabituel au début de déclarer les types sur une ligne séparée, mais après un certain temps, cela commence à paraître naturel.

Langue du client Web

Cela signifie simplement qu'Elm se compile en JavaScript, afin que les navigateurs puissent l'exécuter sur une page Web.

Cela dit, il ne s'agit pas d'un langage à usage général comme Java ou JavaScript avec Node.js, mais d'un langage spécifique à un domaine pour écrire la partie client des applications Web. Plus encore, Elm inclut à la fois l'écriture de la logique métier (ce que fait JavaScript) et la partie présentation (ce que fait HTML), le tout dans un seul langage fonctionnel.

Tout cela est fait dans un cadre très spécifique, appelé The Elm Architecture.

Réactif

L'architecture Elm est un framework Web réactif. Toutes les modifications apportées aux modèles sont rendues immédiatement sur la page, sans manipulation explicite du DOM.

De cette façon, c'est similaire à Angular ou React. Mais Elm le fait aussi à sa manière. La clé pour comprendre ses bases se trouve dans la signature des fonctions de view et de mise à update :

 view : Model -> Html Msg update : Msg -> Model -> Model

Une vue Elm n'est pas seulement la vue HTML du modèle. C'est HTML qui peut produire des messages de type Msg , où Msg est un type d'union exact que vous définissez.

Tout événement de page standard peut produire un message. Et, lorsqu'un message est produit, Elm appelle en interne la fonction de mise à jour avec ce message, qui met ensuite à jour le modèle en fonction du message et du modèle actuel, et le modèle mis à jour est à nouveau rendu en interne dans la vue.

Piloté par les événements

Tout comme JavaScript, Elm est piloté par les événements. Mais contrairement, par exemple, à Node.js, où des rappels individuels sont fournis pour les actions asynchrones, les événements Elm sont regroupés dans des ensembles discrets de messages, définis dans un type de message. Et, comme avec n'importe quel type d'union, les informations transportées par des valeurs de type distinctes peuvent être n'importe quoi.

Il existe trois sources d'événements pouvant produire des messages : les actions de l'utilisateur dans la vue Html , l'exécution de commandes et les événements externes auxquels nous nous sommes abonnés. C'est pourquoi les trois types, Html , Cmd et Sub contiennent msg comme argument. Et, le type générique msg doit être le même dans les trois définitions - le même que celui fourni à la fonction de mise à jour (dans l'exemple précédent, c'était le type Msg , avec un M majuscule), où tout le traitement des messages est centralisé.

Code source d'un exemple réaliste

Vous pouvez trouver un exemple complet d'application Web Elm dans ce référentiel GitHub. Bien que simple, il montre la plupart des fonctionnalités utilisées dans la programmation client quotidienne : récupération de données à partir d'un point de terminaison REST, décodage et codage de données JSON, utilisation de vues, de messages et d'autres structures, communication avec JavaScript et tout ce qui est nécessaire pour compiler et empaqueter Code Elm avec Webpack.

Exemple Web ELM

L'application affiche une liste d'utilisateurs extraits d'un serveur.

Pour un processus de configuration/démo plus facile, le serveur de développement de Webpack est utilisé à la fois pour tout emballer, y compris Elm, et pour servir la liste des utilisateurs.

Certaines fonctionnalités sont en Elm et d'autres en JavaScript. Ceci est fait intentionnellement pour une raison importante : pour montrer l'interopérabilité. Vous voudrez probablement essayer Elm pour commencer, ou y migrer progressivement le code JavaScript existant, ou ajouter de nouvelles fonctionnalités dans le langage Elm. Grâce à l'interopérabilité, votre application continue de fonctionner avec le code Elm et JavaScript. C'est probablement une meilleure approche que de démarrer toute l'application à partir de zéro dans Elm.

La partie Elm dans l'exemple de code est d'abord initialisée avec les données de configuration de JavaScript, puis la liste des utilisateurs est récupérée et affichée dans le langage Elm. Supposons que nous ayons déjà implémenté certaines actions utilisateur dans JavaScript. L'invocation d'une action utilisateur dans Elm ne fait que lui renvoyer l'appel.

Le code utilise également certains des concepts et techniques expliqués dans la section suivante.

Application des concepts d'orme

Passons en revue certains des concepts exotiques du langage de programmation Elm dans des scénarios réels.

Type de syndicat

C'est l'or pur de la langue Elm. Vous souvenez-vous de toutes ces situations où des données structurellement différentes devaient être utilisées avec le même algorithme ? Il est toujours difficile de modéliser ces situations.

Voici un exemple : Imaginez que vous créez une pagination pour votre liste. À la fin de chaque page, il devrait y avoir des liens vers les pages précédentes, suivantes et toutes par leurs numéros. Comment le structurez-vous pour contenir les informations sur le lien sur lequel l'utilisateur a cliqué ?

Nous pouvons utiliser plusieurs rappels pour les clics précédents, suivants et sur les numéros de page, ou nous pouvons utiliser un ou deux champs booléens pour indiquer ce qui a été cliqué, ou donner une signification particulière à des valeurs entières particulières, comme des nombres négatifs, zéro, etc. Mais aucun de ces solutions peuvent modéliser exactement ce type d'événement utilisateur.

Dans Elm, c'est très simple. Nous définirions un type d'union :

 type NextPage = Prev | Next | ExactPage Int

Et nous l'utilisons comme paramètre pour l'un des messages :

 type Msg = ... | ChangePage NextPage

Enfin, nous mettons à jour la fonction pour avoir un case pour vérifier le type de nextPage :

 update msg model = case msg of ChangePage nextPage -> case nextPage of Prev -> ... Next -> ... ExactPage newPage -> ...

Cela rend les choses très élégantes.

Création de plusieurs fonctions de carte avec <|

De nombreux modules incluent une fonction map , avec plusieurs variantes à appliquer à un nombre différent d'arguments. Par exemple, List a map , map2 , … , jusqu'à map5 . Mais que se passe-t-il si nous avons une fonction qui prend six arguments ? Il n'y a pas de map6 . Mais il existe une technique pour surmonter cela. Il utilise le <| fonction en tant que paramètre et fonctions partielles, certains des arguments étant appliqués en tant que résultats intermédiaires.

Pour plus de simplicité, supposons qu'une List n'ait que map et map2 , et nous voulons appliquer une fonction qui prend trois arguments sur trois listes.

Voici à quoi ressemble la mise en œuvre :

 map3 foo list1 list2 list3 = let partialResult = List.map2 foo list1 list2 in List.map2 (<|) partialResult list3

Supposons que nous voulions utiliser foo , qui multiplie simplement ses arguments numériques, définis comme :

 foo abc = a * b * c

Donc le résultat de map3 foo [1,2,3,4,5] [1,2,3,4,5] [1,2,3,4,5] est [1,8,27,64,125] : List number .

Déconstruisons ce qui se passe ici.

Tout d'abord, dans partialResult = List.map2 foo list1 list2 , foo est partiellement appliqué à chaque paire dans list1 et list2 . Le résultat est [foo 1 1, foo 2 2, foo 3 3, foo 4 4, foo 5 5] , une liste de fonctions qui prend un paramètre (car les deux premiers sont déjà appliqués) et renvoie un nombre.

Ensuite dans List.map2 (<|) partialResult list3 , c'est en fait List.map2 (<|) [foo 1 1, foo 2 2, foo 3 3, foo 4 4, foo 5 5] list3 . Pour chaque paire de ces deux listes, nous appelons la fonction (<|) . Par exemple, pour la première paire, c'est (<|) (foo 1 1) 1 , qui est identique à foo 1 1 <| 1 foo 1 1 <| 1 , qui est identique à foo 1 1 1 , qui produit 1 . Pour le second, ce sera (<|) (foo 2 2) 2 , qui est foo 2 2 2 , qui vaut 8 , et ainsi de suite.

Cette méthode peut être particulièrement utile avec les fonctions mapN pour décoder les objets JSON avec de nombreux champs, car Json.Decode les fournit jusqu'à map8 .

Supprimer toutes les valeurs de rien d'une liste de Maybes

Disons que nous avons une liste de valeurs Maybe et que nous voulons extraire uniquement les valeurs des éléments qui en ont une. Par exemple, la liste est :

 list : List (Maybe Int) list = [ Just 1, Nothing, Just 3, Nothing, Nothing, Just 6, Just 7 ]

Et, nous voulons obtenir [1,3,6,7] : List Int . La solution est cette expression d'une ligne :

 List.filterMap identity list

Voyons pourquoi cela fonctionne.

List.filterMap s'attend à ce que le premier argument soit une fonction (a -> Maybe b) , qui est appliquée sur les éléments d'une liste fournie (le deuxième argument), et la liste résultante est filtrée pour omettre toutes les valeurs Nothing , puis le vrai les valeurs sont extraites de Maybe s.

Dans notre cas, nous avons fourni identity , donc la liste résultante est à nouveau [ Just 1, Nothing, Just 3, Nothing, Nothing, Just 6, Just 7 ] . Après filtrage, nous obtenons [ Just 1, Just 3, Just 6, Just 7 ] , et après extraction de la valeur, c'est [1,3,6,7] , comme nous le voulions.

Décodage JSON personnalisé

Comme nos besoins en décodage JSON (ou désérialisation) commencent à dépasser ce qui est exposé dans le module Json.Decode , nous pourrions avoir des problèmes pour créer de nouveaux décodeurs exotiques. C'est parce que ces décodeurs sont appelés au milieu du processus de décodage, par exemple, dans les méthodes Http , et il n'est pas toujours clair quelles sont leurs entrées et sorties, surtout s'il y a beaucoup de champs dans le JSON fourni.

Voici deux exemples pour montrer comment gérer de tels cas.

Dans le premier, nous avons deux champs dans le JSON entrant, a et b , indiquant les côtés d'une zone rectangulaire. Mais, dans un objet Elm, nous ne voulons stocker que sa surface.

 import Json.Decode exposing (..) areaDecoder = map2 (*) (field "a" int) (field "b" int) result = decodeString areaDecoder """{ "a":7,"b":4 }""" -- Ok 28 : Result.Result String Int

Les champs sont décodés individuellement avec le décodeur field int , puis les deux valeurs sont fournies à la fonction fournie dans map2 . Comme la multiplication ( * ) est aussi une fonction, et qu'elle prend deux paramètres, nous pouvons simplement l'utiliser comme ça. Le areaDecoder résultant est un décodeur qui renvoie le résultat de la fonction lorsqu'elle est appliquée, dans ce cas, a*b .

Dans le deuxième exemple, nous obtenons un champ d'état désordonné, qui peut être nul, ou n'importe quelle chaîne, y compris vide, mais nous savons que l'opération a réussi uniquement si elle est "OK". Dans ce cas, nous voulons le stocker en tant que True et pour tous les autres cas en tant que False . Notre décodeur ressemble à ceci :

 okDecoder = nullable string |> andThen (\ms -> case ms of Nothing -> succeed False Just s -> if s == "OK" then succeed True else succeed False )

Appliquons-le à certains JSON :

 decodeString (field "status" okDecoder) """{ "a":7, "status":"OK" }""" -- Ok True decodeString (field "status" okDecoder) """{ "a":7, "status":"NOK" }""" -- Ok False decodeString (field "status" okDecoder) """{ "a":7, "status":null }""" -- Ok False

La clé ici est dans la fonction fournie à andThen , qui prend le résultat d'un précédent décodeur de chaîne nullable (qui est un Maybe String ), le transforme en tout ce dont nous avons besoin et renvoie le résultat sous forme de décodeur avec l'aide de succeed .

Clé à emporter

Comme on peut le voir à partir de ces exemples, la programmation de manière fonctionnelle peut ne pas être très intuitive pour les développeurs Java et JavaScript. Il faut un certain temps pour s'y habituer, avec beaucoup d'essais et d'erreurs. Pour vous aider à le comprendre, vous pouvez utiliser elm-repl pour tester et vérifier les types de retour de vos expressions.

L'exemple de projet lié au début de cet article contient plusieurs autres exemples de décodeurs et d'encodeurs personnalisés qui pourraient également vous aider à les comprendre.

Mais encore, pourquoi choisir Elm ?

Étant si différent des autres frameworks clients, le langage Elm n'est certainement pas "une énième bibliothèque JavaScript". En tant que tel, il possède de nombreux traits qui peuvent être considérés comme positifs ou négatifs par rapport à eux.

Commençons d'abord par le côté positif.

Programmation client sans HTML ni JavaScript

Enfin, vous avez un langage où vous pouvez tout faire. Fini la séparation et les combinaisons maladroites de leur mélange. Pas de génération de HTML en JavaScript et pas de langages de modèles personnalisés avec quelques règles logiques simplifiées.

Avec Elm, vous n'avez qu'une seule syntaxe et un seul langage, dans toute sa splendeur.

Uniformité

Comme presque tous les concepts sont basés sur des fonctions et quelques structures, la syntaxe est très concise. Vous n'avez pas à vous inquiéter si une méthode est définie au niveau de l'instance ou de la classe, ou s'il s'agit simplement d'une fonction. Ce sont toutes des fonctions définies au niveau du module. Et, il n'y a pas cent façons différentes d'itérer des listes.

Dans la plupart des langages, il y a toujours cet argument pour savoir si le code est écrit à la manière du langage. Beaucoup d'idiomes doivent être maîtrisés.

Dans Elm, s'il compile, c'est probablement la méthode "Elm". Si non, eh bien, ce n'est certainement pas le cas.

Expressivité

Bien que concise, la syntaxe Elm est très expressive.

Ceci est réalisé principalement grâce à l'utilisation de types d'union, de déclarations de type formelles et du style fonctionnel. Tous ces éléments inspirent l'utilisation de fonctions plus petites. À la fin, vous obtenez un code qui s'auto-documente à peu près.

Non nul

Lorsque vous utilisez Java ou JavaScript pendant très longtemps, null devient quelque chose de complètement naturel pour vous, une partie inévitable de la programmation. Et, bien que nous voyions constamment NullPointerException s et divers TypeError s, nous ne pensons toujours pas que le vrai problème soit l'existence de null . C'est tellement naturel .

Il devient clair rapidement après un certain temps avec Elm. Ne pas avoir null nous évite non seulement de voir des erreurs de référence null d'exécution encore et encore, cela nous aide également à écrire un meilleur code en définissant et en gérant clairement toutes les situations où nous pourrions ne pas avoir la valeur réelle, réduisant ainsi également la dette technique en ne reportant pas null manipulation jusqu'à ce que quelque chose se casse.

La confiance que cela fonctionnera

La création de programmes JavaScript syntaxiquement corrects peut être réalisée très rapidement. Mais, cela fonctionnera-t-il réellement ? Eh bien, voyons après avoir rechargé la page et l'avoir testée à fond.

Avec Elm, c'est le contraire. Avec la vérification de type statique et les vérifications null appliquées, la compilation prend un certain temps, en particulier lorsqu'un débutant écrit un programme. Mais, une fois compilé, il y a de fortes chances que cela fonctionne correctement.

Vite

Cela peut être un facteur important lors du choix d'un framework client. La réactivité d'une application Web étendue est souvent cruciale pour l'expérience utilisateur, et donc pour le succès de l'ensemble du produit. Et, comme le montrent les tests, Elm est très rapide.

Avantages d'Elm par rapport aux cadres traditionnels

La plupart des frameworks Web traditionnels offrent des outils puissants pour la création d'applications Web. Mais cette puissance a un prix : une architecture trop compliquée avec de nombreux concepts différents et des règles sur comment et quand les utiliser. Il faut beaucoup de temps pour tout maîtriser. Il existe des contrôleurs, des composants et des directives. Ensuite, il y a les phases de compilation et de configuration, et la phase d'exécution. Et puis, il y a des services, des usines et tout le langage de modèle personnalisé utilisé dans les directives fournies - toutes ces situations où nous devons appeler $scope.$apply() directement pour rafraîchir la page, et plus encore.

La compilation d'Elm vers JavaScript est certainement aussi très compliquée, mais le développeur est protégé d'avoir à en connaître tous les rouages. Écrivez simplement du Elm et laissez le compilateur faire son travail.

Et pourquoi ne pas choisir l'orme ?

Assez de louanges à Elm. Voyons maintenant quelques-uns de ses aspects pas si géniaux.

Documentation

C'est vraiment un problème majeur. La langue Elm manque d'un manuel détaillé.

Les tutoriels officiels ne font que survoler la langue et laissent beaucoup de questions sans réponse.

La référence officielle de l'API est encore pire. Beaucoup de fonctions manquent d'explications ou d'exemples. Et puis il y a ceux avec la phrase : « Si cela prête à confusion, suivez le didacticiel Elm Architecture. Ça aide vraiment !" Ce n'est pas la plus grande ligne que vous voulez voir dans les documents officiels de l'API.

Espérons que cela changera bientôt.

Je ne pense pas qu'Elm puisse être largement adopté avec une documentation aussi médiocre, en particulier avec des personnes venant de Java ou de JavaScript, où de tels concepts et fonctions ne sont pas du tout intuitifs. Pour les saisir, une bien meilleure documentation avec beaucoup d'exemples est nécessaire.

Format et espace

Se débarrasser des accolades ou des parenthèses et utiliser un espace blanc pour l'indentation pourrait être agréable. Par exemple, le code Python semble très soigné. Mais pour les créateurs du elm-format , ce n'était pas suffisant.

Avec tous les espaces à double ligne et les expressions et affectations divisées en plusieurs lignes, le code Elm semble plus vertical qu'horizontal. Ce qui serait un one-liner dans le bon vieux C peut facilement s'étendre sur plus d'un écran dans la langue Elm.

Cela peut sembler bon si vous êtes payé par lignes de code écrites. Mais, si vous voulez aligner quelque chose avec une expression commencée 150 lignes plus tôt, bonne chance pour trouver la bonne indentation.

Gestion des enregistrements

Il est difficile de travailler avec eux. La syntaxe pour modifier le champ d'un enregistrement est moche. Il n'existe aucun moyen simple de modifier des champs imbriqués ou de référencer arbitrairement des champs par leur nom. Et si vous utilisez les fonctions d'accès de manière générique, il y a beaucoup de problèmes avec un typage correct.

En JavaScript, un enregistrement ou un objet est la structure centrale qui peut être construite, consultée et modifiée de nombreuses façons. Même JSON n'est qu'une version sérialisée d'un enregistrement. Les développeurs sont habitués à travailler avec des enregistrements dans la programmation Web, de sorte que des difficultés dans leur gestion dans Elm peuvent devenir perceptibles s'ils sont utilisés comme structure de données principale.

Plus de frappe

Elm nécessite plus de code pour être écrit que JavaScript.

Il n'y a pas de conversion de type implicite pour les opérations de chaîne et de nombre, donc de nombreuses conversions int-float et en particulier des appels toString sont nécessaires, ce qui nécessite alors des parenthèses ou des symboles d'application de fonction pour correspondre au nombre correct d'arguments. De plus, la fonction Html.text nécessite une chaîne comme argument. Beaucoup d'expressions de cas sont nécessaires, pour tous ces Maybe s, Results , types, etc.

La principale raison en est le système de type strict, et cela peut être un juste prix à payer.

Décodeurs et encodeurs JSON

Un domaine où le typage se démarque vraiment est la gestion de JSON. Ce qui est simplement un appel JSON.parse() en JavaScript peut s'étendre sur des centaines de lignes dans le langage Elm.

Bien sûr, une sorte de mappage entre les structures JSON et Elm est nécessaire. Mais la nécessité d'écrire à la fois des décodeurs et des encodeurs pour le même morceau de JSON est un problème sérieux. Si vos API REST transfèrent des objets avec des centaines de champs, cela représentera beaucoup de travail.

Emballer

Nous avons vu Elm, il est temps de répondre aux questions bien connues, probablement aussi anciennes que les langages de programmation eux-mêmes : est-il meilleur que la concurrence ? Doit-on l'utiliser dans notre projet ?

La réponse à la première question peut être subjective, car tous les outils ne sont pas des marteaux et tout n'est pas un clou. Elm peut briller et être un meilleur choix par rapport aux autres frameworks de clients Web dans de nombreux cas, tout en étant insuffisant dans d'autres. Mais il offre une valeur vraiment unique qui peut rendre le développement Web frontal beaucoup plus sûr et plus facile que les alternatives.

Pour la seconde question, pour éviter de répondre aussi par le sempiternel « ça dépend », la réponse simple est : Oui. Même avec tous les inconvénients mentionnés, la seule confiance qu'Elm vous donne quant à l'exactitude de votre programme est une raison suffisante pour l'utiliser.

Coder dans Elm est aussi amusant. C'est une perspective totalement nouvelle pour quiconque est habitué aux paradigmes de programmation Web "conventionnels".

En utilisation réelle, vous n'avez pas besoin de basculer immédiatement toute votre application vers Elm ou d'en démarrer une nouvelle complètement. Vous pouvez tirer parti de son interopérabilité avec JavaScript pour l'essayer, en commençant par une partie de l'interface ou certaines fonctionnalités écrites en langage Elm. Vous découvrirez rapidement s'il convient à vos besoins et élargirez ensuite son utilisation ou le quitterez. Et qui sait, vous tomberez peut-être aussi amoureux du monde de la programmation Web fonctionnelle.

Connexes : Déterrer ClojureScript pour le développement frontal