URL: https://linuxfr.org/news/a-la-decouverte-d-un-nouveau-langage-elm Title: À la découverte d'un nouveau langage, Elm Authors: Bruno Michel Davy Defaud, ZeroHeure, VictorAche, palm123, Lucas et Nils Ratusznik Date: 2016年04月13日T21:30:31+02:00 License: CC By-SA Tags: elm et js-fatigue Score: 45 Découvrons un nouveau langage : Elm. Celui-ci vise à rendre accessible la programmation fonctionnelle pour les développeurs Web. JavaScript a ses qualités et ses défauts ; il est parfois intéressant d'aller voir ailleurs pour mieux les comprendre. Même si vous ne comptez pas utiliser Elm plus tard, cela reste intéressant car il vous permettra de découvrir de nouvelles façons de faire et vous permettra de devenir un meilleur développeur. D'ailleurs, on peut noter que de nombreuses bibliothèques JavaScript, comme [Redux](http://redux.js.org/), annoncent clairement s'être inspirées d'Elm. Elm a été créé dans le but d'apporter fiabilité et maintenance simplifiée aux applications JavaScript dans les navigateurs. Son créateur, [Evan Czaplicki](https://twitter.com/czaplic) s'est donc naturellement inspiré des langages fonctionnels, qui sont conçus justement pour avoir ces caractéristiques. En utilisant la bibliothèque JavaScript [virtual-dom](https://github.com/Matt-Esch/virtual-dom), il s'est également assuré que [les performances soient au niveau](http://elm-lang.org/blog/blazing-fast-html) des principaux frameworks. ---- [Le site officiel d'Elm](http://elm-lang.org/) [Evan Czaplicki - Let's be mainstream! (vidéo)](https://www.youtube.com/watch?v=oYk8CKH7OhE) [Awesome Elm, compilation de liens](https://github.com/isRuslan/awesome-elm) [Try Elm](http://elm-lang.org/try) [The Elm Architecture](https://github.com/evancz/elm-architecture-tutorial/) [Et si JavaScript allait droit dans le mur ?](https://linuxfr.org/news/et-si-javascript-allait-droit-dans-le-mur) ---- ![Why Elm is awesome!](https://d262ilb51hltx0.cloudfront.net/max/800/1*EPG-cQfPMecYLSaUwpZf9A.jpeg)> Why Elm is awesome! - [Garrett Rivera](https://dribbble.com/grivera) ---- Personnellement, je code sous vim avec le plugin [Elm-vim](https://github.com/ElmCast/elm-vim) et j'utilise [Elm-format](https://github.com/avh4/elm-format) pour que mon code soit formaté d'une manière gracieuse. Mais pour essayer Elm tout au long de cet article, je vous conseille [l'éditeur en ligne](http://elm-lang.org/try). Commençons par un Hello World : ```haskell import Html exposing (text) main = text "Hello, World!" ``` Dans l'éditeur en ligne, "Hello, World!" devrait s'afficher tout de suite. Ailleurs, il va falloir convertir le code Elm en code JavaScript, puis exécuter celui-ci. La première ligne importe le module Html et expose la fonction text. Celle-ci pourra être appelée directement, sans avoir besoin de préciser le namespace d'où elle vient. Ensuite, on déclare la fonction main. Cette fonction ne prend pas de paramètre et renvoie un élément Html, en l'occurrence le texte "Hello, World!". Elm est un langage fortement typé. Il est recommandé de déclarer le type des méthodes pour détecter plus facilement les erreurs. Mais, pour le moment, nous allons nous reposer sur l'inférence de type d'Elm et laisser ça pour plus tard. Voyons plutôt comment utiliser notre code en dehors de l'éditeur en ligne. Pour ça, il nous faut tout d'abord installer le paquet Html et ses dépendances. Lançons elm-package pour faire ça : ```sh $ elm-package install evancz/elm-html To install evancz/elm-html I would like to add the following dependency to elm-package.json: "evancz/elm-html": "4.0.2 <= v < 5.0.0" May I add that to elm-package.json for you? (y/n) y Some new packages are needed. Here is the upgrade plan. Install: elm-lang/core 3.0.0 evancz/elm-html 4.0.2 evancz/virtual-dom 2.1.0 Do you approve of this plan? (y/n) y Downloading elm-lang/core Downloading evancz/elm-html Downloading evancz/virtual-dom Packages configured successfully! ``` Les outils pour Elm expliquent bien ce qu'ils font et ont des comportements par défaut qui sont pratiques. Cela les rend agréables à utiliser. Si seulement les développeurs JS d'outils comme [Babel](https://babeljs.io/) pouvaient s'en inspirer ! On peut ensuite compiler son fichier elm en fichier html, avec elm-make : ```sh $ elm-make main.elm Success! Compiled 37 modules. Successfully generated index.html ``` On peut aussi générer un fichier JavaScript et écrire soi-même le fichier HTML : ```sh $ elm-make main.elm --output main.js Success! Compiled 1 modules. Successfully generated main.js ``` La compilation est plus rapide la deuxième fois car les modules, et notamment `core`, ont été mis en cache. Cela explique aussi pourquoi le nombre de modules compilés est plus faible. Voyons maintenant un autre exemple, un peu plus compliqué : ```haskell import Graphics.Element exposing (show) length : List a -> Int length list = case list of [] -> 0 first :: rest -> 1 + length rest main = show (length [1..9]) ``` Ici, la fonction main génère une liste avec 9 éléments, de 1 à 9, puis calcule la longueur de cette liste et l'affiche sous forme de texte brut. Ce qui est intéressant dans cet exemple est la définition de la fonction `length`. Cette définition commence avec la déclaration de la signature de la fonction : ```haskell length : List a -> Int ``` La signature est la partie après les `:`. Elle indique que la fonction prend un paramètre, qui est une liste, et retourne un entier (`Int`). Le `a` de `List a` indique que la liste peut être de n'importe quel type. On peut alors réutiliser `a` pour indiquer le même type dans la signature. Par exemple, la fonction `reverse`, qui inverse une liste a pour signature : ```haskell reverse : List a -> List a ``` Les éléments de la liste en paramètre de `reverse` et ceux de la liste retournée sont du même type. Ensuite, l'implémentation de la fonction `length` considère plusieurs cas, grâce au mot-clé `case of`. Le premier cas est celui d'une liste vide. On retourne alors 0. Le deuxième cas fait appel à la récurrence. On prend le premier élément de la liste (`first`) et le reste (`rest`) et on dit que la longueur de la liste est un de plus que la longueur de la liste sans le premier élément. Ainsi, les types peuvent servir à deux choses : détecter des erreurs, mais aussi aider à les corriger. En effet, le compilateur a été pensé pour être un assistant. Ces messages d’erreur ne sont pas juste là pour dire que quelque chose ne va pas, ils vont plus loin. Si vous faites une typo et inversez deux caractères, le compilateur va souvent vous suggérer la bonne version. Il est même possible d'apprendre de nouvelles choses sur le langage via le compilateur. Par exemple, si vous écrivez ce bout de code : ```haskell type alias Repository = { version : String , name : String } showVersion : Repository -> String showVersion repository = "Version: " + repository.version ``` Le compilateur va dire que l'on ne peut pas utiliser `+` pour concaténer des chaînes de caractères, mais que `++` permet de faire ça. Et il donne un lien pour en savoir plus : ```eiffel -- TYPE MISMATCH ------------------------------------------------ Repository.elm The left argument of (+) is causing a type mismatch. 12│ "Version: " + repository.version ^^^^^^^^^^^ (+) is expecting the left argument to be a: number But the left argument is: String Hint: To append strings in Elm, you need to use the (++) operator, not (+). Detected errors in 1 module. ``` Un autre exemple intéressant est [la manipulation d'arbres binaires](http://elm-lang.org/examples/binary-tree) : ```haskell type Tree a = Empty | Node a (Tree a) (Tree a) empty : Tree a empty = Empty singleton : a -> Tree a singleton v = Node v Empty Empty insert : comparable -> Tree comparable -> Tree comparable insert x tree = case tree of Empty -> singleton x Node y left right -> if x> y then Node y left (insert x right) else if x < y then Node y (insert x left) right else tree fromList : List comparable -> Tree comparable fromList xs = List.foldl insert empty xs ``` Sans détailler tout le code, on peut noter qu'il est facile de décrire la structure d'un arbre : soit l'arbre est vide, soit c'est un nœud avec une valeur associée de type `a` et 2 sous-arbres du même type (que l'on nomme généralement `left` et `right`). Cette structure est récursive et il donc logique que l'on retrouve des fonctions récursives pour la manipuler, comme `insert`. Le côté programmation fonctionnelle ressort également de manière assez marquée dans cet exemple, que ce soit pour la ligne `List.foldl insert empty xs`, qui peut sembler magique à première vue, mais que l'on apprend rapidement à maîtriser, ou dans la signature de la fonction `insert`. C'est une fonction qui prend 2 arguments, un élément et un arbre, et retourne un nouvel arbre. Mais on peut aussi voir ça comme une fonction qui prend un élément et qui va retourner une fonction qui modifie un arbre en un nouvel arbre. Bien sûr, si on appelle la fonction avec 2 arguments, un élément et un arbre compatible, cela fait la même chose : renvoyer un nouvel arbre avec l'élément inséré. Mais on peut aussi s'en servir avec un seul paramètre pour créer une fonction intermédiaire : ```haskell insertZero : Tree Int -> Tree Int insertZero = insert 0 aListOfTrees = [ fromList [1, 2, 3] , fromList [4, 5, 6] , fromList [7, 8, 9] ] anotherList = List.map insertZero aListOfTrees ``` La programmation fonctionnelle fait partie des gènes d'Elm. C'est déroutant au début, mais ça se révèle être un outil très puissant par la suite, tout particulièrement quand on le combine avec le côté programmation réactive d'Elm. En effet, Elm propose d'organiser son code d'une certaine façon, en séparant la logique en 3 parties : - model - update - view Cela revient à partir de ce squelette et l'enrichir au fur et à mesure : ```haskell -- MODEL type alias Model = { ... } -- UPDATE type Action = NoOp | ... update : Action -> Model -> Model update action model = case action of NoOp -> action ... -- VIEW view : Model -> Html view = ... ``` Pour aller plus loin (et j’espère que cet article vous en aura donné l’envie), je vous conseille la lecture de [_The Elm Architecture_](https://github.com/evancz/elm-architecture-tutorial/). Vous pouvez aussi lire le code de [_elm-peer-tweet_](https://github.com/rogeriochaves/elm-peer-tweet), une implémentation en Elm de PeerTweet, un réseau social distribué qui s’appuie sur les DHT de Bittorrent. Enfin, pour les Parisiens, vous pouvez rencontrer d’autres développeurs lors des [_Meetups Elm Paris_](http://www.meetup.com/fr-FR/Meetup-Elm-Paris/). Cette découverte du langage fait bien entendu l’impasse sur beaucoup de choses. J’aurais pu parler des outils qui offrent un certain gain de productivité (par exemple, `elm-package` s’assure que les modules respectent le _semantic versioning_ en analysant la signature des fonctions) ou de l’interaction avec le JavaScript via les _ports_. Elm n’est pas parfait (pas encore, du moins) : le JavaScript généré est assez gros actuellement (il y a des travaux en cours sur le compilateur pour optimiser ça dans la prochaine version), certaines choses sont difficiles à faire (en général, ce qui implique des effets de bord), etc. Mais je ne saurais trop vous encourager à essayer par vous‐même ! P.‐S. : merci aux personnes qui ont relu cette dépêche pour en corriger les fautes et proposer des améliorations.

AltStyle によって変換されたページ (->オリジナル) /