2 points par GN⁺ 3 시간 전 | 1 commentaires | Partager sur WhatsApp
  • L’inférence de types et la vérification de types progressive s’appliquent à tous les programmes Elixir, ce qui permet de détecter du code mort et des bogues avérés qui échoueront forcément à l’exécution, même sans annotations de type
  • Le type dynamic(), contrairement à any() qui « autorise tout », suit à l’exécution l’éventail des types possibles et ne signale une violation que lorsqu’il ne recoupe pas du tout les types autorisés
  • Une valeur dynamic(integer() or binary()) ne déclenche pas de violation pour des appels où certaines possibilités se recoupent, comme des opérations numériques ou des fonctions de chaîne, mais en déclenche une pour des appels qui n’acceptent que des maps, comme Map.fetch!
  • dynamic() se restreint selon la manière dont il est utilisé, et affine data en une map de la forme %{..., a: number(), b: number()} dans du code comme data.a + data.b
  • Dans les guards, les unions, intersections et négations sont inférées, ce qui permet d’utiliser comme information de type des conditions comme is_list, is_integer, is_map_key, not is_map_key et tuple_size
  • Les case et les conditionnels répercutent les informations des clauses précédentes sur les suivantes, en effectuant par exemple une vérification de type qui traite d’abord nil, puis restreint la valeur restante à binary()
  • Des types ont été ajoutés à plusieurs fonctions de la bibliothèque standard liées aux tuples et aux maps, ce qui aide à repérer des clauses redondantes et du code mort dans les bases de code existantes
  • Dans « If T: Benchmark for Type Narrowing », 12 catégories sur 13 sont validées, montrant qu’il est possible de retrouver des informations de type précises dans du code Elixir classique
  • La v1.20 améliore de nouveau les temps de compilation des applications en environnement multicœur, et dans des benchmarks synthétiques, l’outil de build d’Elixir obtient les meilleurs résultats parmi les langages BEAM
  • La nouvelle option du compilateur :module_definition permet de choisir le mode d’exécution de la définition d’un module, avec la valeur par défaut :compiled ou :interpreted, et s’active via elixirc_options: [module_definition: :interpreted] dans mix.exs
  • L’option :module_definition n’affecte pas les fichiers .beam écrits sur disque et change uniquement le mode d’exécution à l’intérieur de defmodule, ce qui peut aider à améliorer les temps de compilation dans les grands projets
  • Les nouvelles signatures de type s’appuyant sur les types ensemblistes devraient être discutées avec la définition de typed structs, une fois résolus les travaux sur les performances du système de types de la v1.20, les types récursifs, les types paramétrés et l’itération key-value des maps

1 commentaires

 
GN⁺ 3 시간 전
Avis sur Hacker News
  • C’est peut-être juste mon expérience personnelle, mais j’ai l’impression que si un langage n’a pas eu de types dès le départ, ça ne fonctionne jamais aussi bien qu’un vrai langage à typage statique

    • D’accord, mais il y a aussi un autre point de vue : « Why are gradual static types so great? » https://www.benkuhn.net/gradual/
    • À l’inverse, TypeScript doit prendre en charge toutes sortes de schémas étranges que les gens ont pratiqués dans un langage sans types, et c’est justement pour ça qu’il est devenu mon système de types préféré
  • Je travaille comme développeur Elixir professionnel depuis une dizaine d’années et j’attendais depuis longtemps l’arrivée des types. Je suis vraiment ravi de voir que ce début est enfin là dans cette version
    Cela dit, j’aimerais savoir comment l’état de v1.20 se compare à Dialyzer sans spécifications. Si je comprends bien, l’approche de success typing de Dialyzer se rapproche davantage de « s’il existe au moins une combinaison d’arguments qui fonctionne, on n’émet pas d’avertissement » que de « s’il existe une combinaison d’arguments susceptible d’échouer, on émet un avertissement », et je pensais qu’Elixir faisait ici quelque chose de similaire ; or je n’ai jamais trouvé Dialyzer particulièrement utile

    • Je suis curieux de voir ce que cela va dénicher dans une base de code Elixir de 10 ans encore en production
  • J’ai vu passer plusieurs fois sur HN des articles sur le système de types progressif d’Elixir, sans vraiment les suivre en détail. Je me demande si quelqu’un sait si ce système de types progressif peut changer la complexité asymptotique d’un programme par rapport à du code non typé
    À ma connaissance, la plupart des systèmes de types progressifs, comme Racket par exemple, peuvent rendre un programme asymptotiquement plus lent, avec quelques exceptions [1]
    [1] https://doi.org/10.1145/3314221.3314627

    • Le système de types progressif d’Elixir ne peut pas changer la complexité asymptotique d’un programme. Par conception, il exclut explicitement les casts d’exécution aux frontières statique/dynamique qui sont la cause des ralentissements dans d’autres systèmes de types progressifs
      La plupart des systèmes de types progressifs insèrent des contraintes quand une valeur franchit la frontière entre code typé et non typé. Par exemple, en vérifiant tous les éléments d’une liste ou en enveloppant une valeur dans un proxy de type. Mais l’équipe Elixir a publié le résultat strong arrows pour obtenir cette solidité sans ces vérifications à l’exécution, et le bytecode produit par le compilateur est sémantiquement identique à celui du code non typé
  • Ironiquement, les critiques disaient qu’il fallait des types, et les fans d’Elixir répondaient qu’il n’en fallait pas, qu’Elixir était magique d’une certaine manière et qu’il n’y avait donc pas de bugs liés aux types. Maintenant qu’ils ajoutent des types, ils trouvent des bugs. Ce n’était pas censé être inutile pour prévenir les bugs ? Cela reste malgré tout un bon changement. J’ai pas mal utilisé Elixir autrefois et j’aimais bien, mais il m’était difficile d’accepter l’absence de types

    • C’est la Goomba fallacy
      https://en.wiktionary.org/wiki/Goomba_fallacy
    • Je n’ai pas suivi Elixir de très près, mais ce que j’ai vu côté discussions Erlang était un peu différent. Puisqu’il faut de toute façon gérer proprement les échecs, l’idée était que les erreurs de type peuvent simplement être traitées avec les mécanismes de reprise après échec qu’il faut déjà avoir en place
      Je ne suis pas d’accord avec ce point de vue, mais c’est une position bien plus défendable que « $LANGUAGE est magique »
    • Je ne peux pas garantir que personne n’a jamais tenu ce genre de discours, mais je ne m’en souviens pas, et même si cela a existé, cela devait être extrêmement minoritaire. En pratique, l’argument opposé ressemblait plutôt à ceci : « les types, c’est bien, mais cela a un coût, et ce coût n’apporte pas toujours un retour suffisant »
      Avant les avancées de la théorie des types ensembliste, cette position était peut-être justifiée
    • La même chose s’est produite en JavaScript/TypeScript et en Python. Parfois, il faut simplement laisser les gens croire ce qu’ils veulent croire
    • C’est le cycle de la vie. Les langages à typage dynamique se font des fans, puis d’autres disent — à juste titre — qu’ils seraient bien plus utiles avec du typage statique. Les fans le prennent personnellement et répondent qu’il n’y a pas besoin de typage statique. Les raisons varient : « de toute façon ce n’est pas utile », « cela va à l’encontre de l’esprit du langage », « ce n’est qu’un langage de script », « il suffit d’utiliser un débogueur », « le typage statique nuit à la productivité », etc.
      Puis, au final, on ajoute le typage statique. C’est arrivé à Python, JavaScript et Ruby, et il y en a sûrement d’autres
  • J’adore le fait qu’on puisse mettre à jour Elixir sans changements cassants dans plusieurs projets, et que le compilateur trouve gratuitement des bugs. Je m’y suis trop habitué

  • Ça me fait vraiment plaisir à voir. On se rapproche maintenant vraiment du niveau de « grand langage », et pour moi Elixir est le premier candidat
    Si vous connaissez un autre langage déjà agréable à utiliser et qui continue malgré cela à ajouter d’excellentes fonctionnalités de manière stable et sûre, je suis preneur. J’étais en train de bien maîtriser Go avant de me tourner vers l’apprentissage du C# avancé, parce que j’avais l’impression que Go avait cessé d’ajouter de bonnes fonctionnalités

  • J’ai suivi la piste Elixir sur exercism.io le mois dernier https://exercism.org/tracks/elixir
    C’est vraiment excellent

  • Ah, ça recommence. Je vais sans doute réapprendre Elixir pendant encore un an
    J’adore tout dans Elixir, mais plus que n’importe quel autre langage, Elixir me pousse à douter de moi-même en permanence. Mon cerveau ne semble pas fait pour le fonctionnel, mais ce changement me donne envie de réessayer
    Ce qui est dommage, c’est qu’on ne peut pas vraiment dire que l’écosystème soit accueillant pour les débutants, et quand on répond aux questions, on part souvent du principe que la personne connaît déjà très bien le langage

    • https://pragprog.com/titles/lhelph/functional-web-developmen...
      Ne vous laissez pas tromper par le titre. La première moitié du livre, c’est simplement Elixir
      Depuis 8 ans, à chaque fois que je me remets à Elixir, je reprends ce livre, et à chaque fois ça marche bien. Je ne l’ai jamais lu jusqu’au bout
      L’un de mes critères pour juger si ce genre de livre de programmation en mode projet/tutoriel est bon, c’est de savoir s’il me donne déjà, vers le milieu, les outils pour aller faire mon vrai travail, même si je l’ai commencé plusieurs fois sans jamais le terminer
    • J’ai vraiment vécu ça dans la douleur la première fois que j’ai touché à Haskell, dans un cours du genre « vue d’ensemble des paradigmes de programmation » à l’université. Je programmais déjà depuis quelques années, et je n’arrivais pas à croire qu’on puisse se sentir aussi impuissant face à des choses qu’on considérait comme élémentaires depuis si longtemps
      Mais à mon avis, ce n’est pas tant une question de cerveau pas adapté qu’un contraste entre le niveau d’expérience accumulé dans les langages impératifs et le fait de redevenir débutant dans un style purement fonctionnel
      Ça ira de mieux en mieux. Le déclic qui m’a mis à l’aise avec la programmation fonctionnelle, ça a été de réaliser à quel point j’aimais assembler du code façon « one-liners » Bash bien aérés. Quand les données commencent sous une certaine forme, je les dump avec une commande, je réfléchis à l’étape qui les rapproche de la forme voulue, je les passe par un pipe vers la commande suivante, puis j’inspecte à nouveau. En continuant ainsi, on se retrouve généralement à la fin avec une suite de transformations de données qui ne les modifient pas en place
      L’une des raisons pour lesquelles c’est confortable dans le shell, c’est qu’on se promène tous les jours dans le système de fichiers tout en accumulant du vocabulaire de commandes. Dans un environnement de type Unix, la bibliothèque de « fonctions » familières devient assez grande au fil des années. Dans un environnement de programmation purement fonctionnelle, il faut faire la même chose, mais apprendre le vocabulaire demande un peu plus d’effort. Les « commandes » qu’on utilise souvent deviennent des fonctions comme map, fold, zip au lieu de grep, cat, sort
      Mais au fond, c’est vraiment la même chose, et l’attrait de construire des pipelines s’applique pareil des deux côtés. On peut avancer morceau par morceau, et à chaque étape du puzzle, oublier l’étape précédente pour se concentrer seulement sur la façon de transformer les données qu’on a sous les yeux. Cette faible charge contextuelle est rafraîchissante et confortable
      J’espère vraiment que tu essaieras et que tu y prendras goût. C’est quand on apprend à apprécier le fait de ne pas encore savoir faire quelque chose qu’on finit par devenir bon
    • Je me demande si tu connais un peu Rust. Je n’ai pas non plus énormément d’expérience avec les langages fonctionnels, mais Gleam m’a semblé familier grâce à ses côtés rustiens, ce qui m’a permis de me concentrer davantage sur les concepts que sur la syntaxe
      Bien sûr, je n’y ai passé que quelques après-midis, mais si je devais rééduquer mon cerveau au fonctionnel, je choisirais probablement Gleam pour ce sentiment de familiarité
    • Je te recommande de poser la question sur ElixirForum. Je n’y ai jamais vu de réactions vraiment hostiles
      Il y a parfois des messages qui n’attirent pas l’attention parce qu’ils sont flous, ou qu’on ignore parce qu’ils sentent le « faites mes devoirs à ma place »
      Mais les messages qui traduisent une vraie curiosité reçoivent tous une réponse, de ce que j’ai vu
    • Ce genre de remarque me laisse toujours perplexe. Un programme orienté objet saturé d’état me paraît bien plus difficile à raisonner
  • Excellent. En 1.20, la compilation de notre grosse application umbrella semble être devenue nettement plus rapide

  • Je me demande comment ça se compare à Gleam. Ou alors, pourquoi utiliser Elixir plutôt que Gleam maintenant ? J’imagine que Phoenix, et surtout LiveView, restent un gros atout pour Elixir

    • C’est la différence entre aimer Rust et aimer Erlang. Utiliser Gleam donne l’impression d’utiliser Rust, tandis qu’utiliser Elixir donne l’impression d’utiliser Erlang
      Je ne connais pas l’état actuel de Gleam OTP, mais la dernière fois que j’ai regardé, ce n’était pas terrible
      Si tout t’est égal à part les types, alors prends Gleam. Mais dans ce cas, pourquoi ne pas simplement utiliser Rust ?
    • Il y a directement un comparatif sur le site de Gleam
    • Gleam n’a pas de macros, et beaucoup de bibliothèques Elixir comme Phoenix ou Ecto utilisent les macros de façon très efficace
      Par exemple, dans Gleam, le décodage/encodage JSON a tendance à devenir verbeux. En Rust, il suffit de dériver serde, et en Elixir, un simple appel de fonction suffit
      Elixir a un écosystème plus mature. Par exemple, on peut utiliser Phoenix depuis Gleam, ou d’autres frameworks Gleam, mais l’expérience n’est pas la même
      La grande raison pour laquelle Gleam attire plus qu’Elixir, ce sont les types, et Elixir est justement en train de réduire cet écart. Il y a aussi le fait qu’il puisse compiler vers JavaScript ; côté Elixir, Hologram fait quelque chose de similaire
      Personnellement, je préfère le système de types de Gleam et sa syntaxe proche de Rust, mais pour l’instant, Elixir me semble être un meilleur choix pour tous mes projets de développement web
    • C’est essentiellement à cause de Phoenix et Ecto