Aventures de l'opérateur de pipeline à babel @ 7


La version babel@7.0.0-beta52 a un nouvel indicateur de configuration requis pour le @babel/plugin-proposal-pipeline-operator , qui rompt la compatibilité descendante pour les versions précédentes du plugin. Dans cet article, vous apprendrez ce qu'est l'opérateur de pipeline et pourquoi il a besoin d'une configuration.


UPD: les pipelines intelligents sont apparus dans babel@7.2.0: https://babeljs.io/blog/2018/12/03/7.2.0#smart-pipeline-operator-parsing-8289-https-githubcom-babel-babel- pull-8289


Statut actuel


Gilbert Garza , qui avait initialement proposé l'opérateur de pipeline , a cherché à obtenir une syntaxe simple pour «les chaînes ordonnées d'appels de fonction dans un style fonctionnel lisible». L'opérateur de pipeline provient de langages tels que F #, Hack, Elm, Elixir et d'autres, et lorsque vous l'ajoutez à JavaScript, deux problèmes litigieux se posent:


  • Où et comment utiliser les espaces réservés?
  • Comment async / await dans un pipeline?

Espaces réservés


La première question a été soulevée par Kevin Smith dans ce billet , où il a suggéré d'utiliser le style de pipe de la langue Hack . Dans Hack, des espaces réservés sont requis pour tout côté droit du pipeline, par exemple:


 namespace Hack\UserDocumentation\Operators\Pipe\Examples\MapFilterCountPiped; function piped_example(array<int> $arr): int { return $arr |> \array_map($x ==> $x * $x, $$) |> \array_filter($$, $x ==> $x % 2 == 0) |> \count($$); } var_dump(piped_example(range(1, 10))); 

Nous avons pris comme base que l'espace réservé peut être utilisé dans n'importe quelle expression et contient la valeur de la dernière étape du pipeline. Cette approche nous donne de la flexibilité et de nombreuses occasions d'écrire des expressions.


Le revers de la médaille est la complexité de la langue due à l'ajout d'un nouveau jeton. Jusqu'à présent, nous avons choisi un hachage ( # ), et bien que la discussion soit toujours ouverte, tout jeton aura potentiellement des intersections avec d'autres utilisations. Par exemple, le hachage est également utilisé par les champs privés de la classe , tout comme les autres variantes de jeton sont utilisées de toute façon .


Async / attente


La première version de l'instruction pipeline contenait cette syntaxe pour await :


 x |> await f 

ce qui peut être déployé pour:


 await f(x) 

Malheureusement, les utilisateurs peuvent très bien s'attendre à un tel déploiement:


 (await f)(x) 

Bien que l'idée même d'ajouter async au pipeline dérapé, les membres du comité se sont prononcés contre un opérateur de pipeline qui ne prend pas en charge l' async / await . Oui, il existe des options pour travailler avec des fonctions qui renvoient Promise sans syntaxe explicite, mais toutes ces options sont trop lourdes ou nécessitent des fonctions auxiliaires.


Solutions suggérées


À la suite des discussions, deux propositions ont été formulées (en plus de l'option minimale): utiliser des F -piplines et des Smart-pipelines. Regardons ces suggestions.


Option opérateur minimale


Cette offre s'applique uniquement aux fonctionnalités de base. Dans la version minimale, la prise en charge de l'asynchronie est supprimée et il n'y a pas d'espace réservé. Cette option correspond au comportement du plugin babel des versions précédentes, avant l'apparition de la configuration, et correspond à la spécification actuelle de l'opérateur de pipeline dans le référentiel. Il est davantage utilisé comme un projet de sondage pour identifier les avantages et les inconvénients d'autres propositions, et il est peu probable qu'il soit accepté sans les changements fondamentaux qui se trouvent dans les propositions alternatives.


Pipelines F #


Les espaces réservés pour les pipelines F # ne sont pas du tout nécessaires. Dans la version de base, les fonctions fléchées couvrent le besoin d'espaces réservés, nécessitant moins de griffonnage, et sont basées sur la syntaxe ES2015 familière à tout le monde.


À l'heure actuelle (selon la spécification des lignes F #), les fonctions fléchées doivent être placées entre crochets:


 let person = { score: 25 }; let newScore = person.score |> double |> (_ => add(7, _)) |> (_ => boundScore(0, 100, _)); 

Des enquêtes sont en cours pour déterminer s'il est possible d'utiliser des fonctions fléchées sans parenthèses, qui semblent ici syntaxiquement redondantes.


Quant à l'asynchronie, await fonctionne comme une fonction unaire dans les pipelines F #:


 promise |> await 

Ce qui se déroule:


 await promise 

et donc await peut être utilisé au milieu d'une longue chaîne d'appels asynchrones:


 promise |> await |> (x => doubleSay(x, ', ')) |> capitalize |> (x => x + '!') |> (x => new User.Message(x)) |> (x => stream.write(x)) |> await |> console.log; 

Un tel traitement d' await spécial peut potentiellement ouvrir la possibilité d'utiliser de manière similaire d'autres opérateurs unaires (par exemple, typeof ), mais la spécification d'origine des canaux F # ne les contient pas.


Pipelines intelligents


Les pipelines Smar amènent l'idée des espaces réservés à leur conclusion logique, permettant à la fois une utilisation partielle et des expressions arbitraires dans les lignes directrices. La chaîne longue précédente peut s'écrire comme ceci:


 promise |> await # |> doubleSay(#, ', ') |> # || throw new TypeError() |> capitalize |> # + '!' |> new User.Message(#) |> await stream.write(#) |> console.log; 

Les règles d'utilisation des espaces réservés dans les pipelines intelligents sont assez simples. Si un seul identifiant est passé à l'étape du pipeline, alors aucun jeton supplémentaire (espace réservé) n'est requis, cela s'appelle le "style nu" :


 x |> a; x |> fb; 

Contrairement à Hack, les fonctions unaires ne nécessitent pas de jeton d'espace réservé.


Pour d'autres expressions, un espace réservé (appelé «jeton de sujet lexical») est requis, et un pipeline est considéré comme fonctionnant dans le «style de thème» - «style de sujet» . L'absence d'un jeton d'espace réservé dans ce cas provoque une erreur SyntaxError précoce:


 10 |> # + 1; promise |> await #; 

S'il existe des opérateurs, des crochets (y compris pour appeler une méthode), des guillemets ou toute autre chose à l'exception d'un identifiant et d'un point, le jeton d'espace réservé est requis. Cela permettra d'éviter de se faire tirer dans le pied et d'éliminer l'incertitude.


Les pipelines intelligents résolvent le problème de la prise en charge de l'asynchronie d'une manière plus générale, ce qui nous permet d'utiliser toutes les expressions possibles dans les pipelines, non seulement en await , mais aussi typeof , yield et tout autre opérateur.


Babel entre en scène


Dès que les trois propositions se sont concrétisées, nous sommes parvenus à la conclusion que de telles discussions n'aboutiraient pas à la résolution de contradictions profondes entre les propositions. Nous avons décidé que la meilleure façon était de recueillir les commentaires des développeurs en utilisant des phrases en code réel. Compte tenu du rôle de Babel dans la communauté des développeurs, nous avons décidé d'ajouter les trois options au plugin d'opérateur de pipeline .


Étant donné que l'analyse des trois phrases est légèrement, mais différente, leur support doit d'abord être ajouté à @babel/parser (qui est babylon ), et l'analyseur doit savoir quelle proposition doit être prise en charge maintenant. Ainsi, le plugin d'opérateur de pipeline nécessite l'option "proposal" , à la fois pour configurer babylon pour l'analyse et pour la transformation ultérieure.


Nous avons travaillé sur ce site en ligne car nous devons apporter toutes les modifications pour rompre la compatibilité descendante avant que babel @ 7 cesse d'être bêta. En fin de compte, nous aimerions rendre l'une des options de pipeline par défaut pour le plugin afin de se débarrasser du besoin d'une option de configuration.


Compte tenu de ces limitations, nous avons décidé d'ajouter une option à la configuration du plugin et de la rendre obligatoire, forçant les utilisateurs à décider laquelle des offres ils souhaitent utiliser dans leur projet. Dès qu'une proposition spécifique est choisie comme comportement canonique de l'opérateur, nous marquons l'option "proposal" comme obsolète, et l'option canonique fonctionnera par défaut. La prise en charge des offres annulées fonctionnera jusqu'à la prochaine version majeure.


Participez


Si vous souhaitez participer à la discussion de la proposition, toutes les discussions sont publiques et vous pouvez les trouver dans le référentiel de la proposition de l'opérateur de pipeline . Une présentation de la réunion TC39 est également à votre service. À la fin, vous pouvez suivre James DiGioia , JS Choi ou Daniel Ehrenberg sur Twitter.


Mais plus important encore, dès que le travail sur le pipeline est terminé, essayez-le dans vos projets! Nous travaillons également sur l'ajout de nouvelles fonctionnalités à remplacer , afin que vous puissiez vérifier votre code de manière interactive. Nous avons besoin de commentaires et l'utiliser dans du vrai code aidera vraiment à l'assembler. Publiez des tweets sur @babeljs .

Source: https://habr.com/ru/post/fr418125/


All Articles