Abenteuer des Pipelinebetreibers in babel @ 7


Die Version babel@7.0.0-beta52 verfügt über ein neues erforderliches Konfigurationsflag für das @babel/plugin-proposal-pipeline-operator , das die Abwärtskompatibilität für frühere Versionen des Plugins beeinträchtigt. In diesem Artikel erfahren Sie, was der pipeline Operator ist und warum er konfiguriert werden muss.


UPD: Smart Pipelines erschienen unter 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


Aktueller Status


Gilbert Garza , der ursprünglich den pipeline Betreiber vorgeschlagen hatte , wollte eine einfache Syntax für "geordnete Ketten von Funktionsaufrufen in einem lesbaren Funktionsstil" erhalten. Der Pipeline-Operator stammt aus Sprachen wie F #, Hack, Elm, Elixir und anderen. Wenn Sie ihn zu JavaScript hinzufügen, treten zwei strittige Probleme auf:


  • Wo und wie werden Platzhalter verwendet?
  • Wie soll async / await in einer Pipeline async / await ?

Platzhalter


Die erste Frage wurde von Kevin Smith in diesem Ticket aufgeworfen, wo er vorschlug, den Pipe- Stil aus der Hack-Sprache zu verwenden . In Hack sind Platzhalter für jede rechte Seite der Pipeline erforderlich, zum Beispiel:


 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))); 

Wir haben davon ausgegangen, dass der Platzhalter in jedem Ausdruck verwendet werden kann und den Wert des letzten Pipeline-Schritts enthält. Dieser Ansatz gibt uns Flexibilität und ausreichend Gelegenheit, Ausdrücke zu schreiben.


Die Kehrseite der Medaille ist die Komplexität der Sprache aufgrund des Hinzufügens eines neuen Tokens. Bisher haben wir einen Hash ( # ) ausgewählt, und obwohl die Diskussion noch offen ist, hat jedes Token möglicherweise Schnittpunkte mit anderen Verwendungen. Beispielsweise wird der Hash auch von privaten Feldern der Klasse verwendet , genau wie alle anderen Token-Varianten, die ohnehin verwendet werden .


Async / warten


Die erste Version der pipeline Anweisung enthielt diese Syntax für das await :


 x |> await f 

Was kann bereitgestellt werden für:


 await f(x) 

Leider können Benutzer eine solche Bereitstellung durchaus erwarten:


 (await f)(x) 

Während die Idee, der pipeline Async hinzuzufügen, ins Wanken geriet, sprachen sich die Ausschussmitglieder gegen einen pipeline Betreiber aus, der async / await nicht unterstützt. Ja, es gibt Optionen für die Arbeit mit Funktionen, die Promise ohne explizite Syntax zurückgeben. Alle diese Optionen sind jedoch zu umständlich oder erfordern Zusatzfunktionen.


Lösungsvorschläge


Als Ergebnis der Diskussionen wurden zwei Vorschläge (zusätzlich zur Minimaloption) formuliert: Verwenden Sie F # -Piplines und Smart-Pipelines. Schauen wir uns diese Vorschläge an.


Minimale Bedieneroption


Dieses Angebot gilt nur für Grundfunktionen. In der Minimalversion wird die Unterstützung für Asynchronität entfernt und es gibt keine Platzhalter. Diese Option entspricht dem Verhalten des Babel-Plugins früherer Versionen, bevor die Konfiguration angezeigt wird, und entspricht der aktuellen Spezifikation für den pipeline Operator im Repository. Es wird eher als Entwurf einer Sonde verwendet, um die Vor- und Nachteile anderer Vorschläge zu ermitteln, und es ist unwahrscheinlich, dass es ohne die grundlegenden Änderungen in alternativen Vorschlägen akzeptiert wird.


F # Pipelines


Platzhalter für F # -Pipelines werden überhaupt nicht benötigt. In der Basisversion decken Pfeilfunktionen den Bedarf an Platzhaltern ab, erfordern weniger Kritzeleien und basieren auf der allen bekannten ES2015-Syntax.


Im Moment (gemäß der Spezifikation der F # -Linien) sollten Pfeilfunktionen in Klammern gesetzt werden:


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

Es werden Umfragen durchgeführt, um festzustellen, ob es möglich ist, Pfeilfunktionen ohne Klammern zu verwenden, die hier syntaktisch redundant erscheinen.


Bei der Asynchronität funktioniert "Warten" als unäre Funktion in F # -Pipelines:


 promise |> await 

Was entfaltet sich in:


 await promise 

und daher kann await mitten in einer langen Kette von asynchronen Aufrufen verwendet werden:


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

Eine solche spezielle await kann möglicherweise die Möglichkeit eröffnen, andere unäre Operatoren (z. B. typeof ) auf ähnliche Weise zu verwenden, aber die ursprüngliche Spezifikation von F # -Rohren enthält sie nicht.


Intelligente Pipelines


Smar-Pipelines bringen die Idee der Platzhalter zu ihrer logischen Schlussfolgerung und ermöglichen sowohl die teilweise Verwendung als auch willkürliche Ausdrücke in den Piplines. Die vorherige lange Kette kann folgendermaßen geschrieben werden:


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

Die Regeln für die Verwendung von Platzhaltern in intelligenten Pipelines sind recht einfach. Wenn ein einzelner Bezeichner an den Pipeline-Schritt übergeben wird, ist kein zusätzliches Token (Platzhalter) erforderlich. Dies wird als "nackter Stil" bezeichnet :


 x |> a; x |> fb; 

Im Gegensatz zu Hack benötigen unäre Funktionen kein Platzhalter-Token.


Für andere Ausdrücke ist ein Platzhalter (als "lexikalisches Themen-Token" bezeichnet) erforderlich, und eine Pipeline funktioniert innerhalb des "Themenstils" - "Themenstil" . Das Fehlen eines Platzhalter-Tokens führt in diesem Fall zu einem frühen SyntaxError-Fehler:


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

Wenn Operatoren, Klammern (einschließlich zum Aufrufen einer Methode), Anführungszeichen oder andere Elemente außer einem Bezeichner und einem Punkt vorhanden sind, ist das Platzhaltertoken erforderlich. Dies hilft, einen Schuss in den Fuß zu vermeiden und Unsicherheiten zu vermeiden.


Intelligente Pipelines lösen das Problem der allgemeineren Unterstützung der Asynchronität, sodass wir alle möglichen Ausdrücke in Pipelines verwenden können, nicht nur await , sondern auch typeof , yield und andere Operatoren.


Babel betritt die Szene


Sobald alle drei Vorschläge konkretisiert waren, kamen wir zu dem Schluss, dass solche Diskussionen nicht zur Lösung tiefer Widersprüche zwischen den Vorschlägen führen würden. Wir haben beschlossen, dass der beste Weg darin besteht, Feedback von Entwicklern mithilfe von Sätzen in echtem Code zu sammeln. Angesichts der Rolle von Babel in der Entwicklergemeinde haben wir beschlossen, alle drei Optionen zum pipeline Betreiber-Plugin hinzuzufügen.


Da das Parsen für alle drei Sätze geringfügig, aber unterschiedlich ist, muss ihre Unterstützung zuerst zu @babel/parser babylon ( babylon ) babylon , und der Parser muss wissen, welcher Vorschlag jetzt unterstützt werden soll. Daher benötigt das pipeline Operator-Plugin die Option "proposal" , sowohl zum Konfigurieren von Babylon für das Parsen als auch für die nachfolgende Transformation.


Wir haben online daran gearbeitet, weil wir alle Änderungen vornehmen müssen, die die Abwärtskompatibilität beeinträchtigen, bevor babel @ 7 nicht mehr Beta ist. Am Ende möchten wir eine der Pipeline-Optionen als Standard für das Plugin festlegen, um die Notwendigkeit einer Konfigurationsoption zu beseitigen.


Angesichts dieser Einschränkungen haben wir beschlossen, der Plugin-Konfiguration eine Option hinzuzufügen und diese obligatorisch zu machen, sodass Benutzer entscheiden müssen, welches der Angebote sie in ihrem Projekt verwenden möchten. Sobald ein bestimmter Vorschlag als kanonisches Verhalten des Operators ausgewählt wird, markieren wir die Option "proposal" als veraltet, und die kanonische Option funktioniert standardmäßig. Die Unterstützung für stornierte Angebote funktioniert bis zur nächsten Hauptversion.


Teilnehmen


Wenn Sie an der Diskussion des Vorschlags teilnehmen möchten, sind alle Diskussionen öffentlich und können im Repository des Vorschlags des Pipeline-Betreibers gefunden werden . Eine Präsentation des TC39-Meetings steht Ihnen ebenfalls zur Verfügung. Am Ende können Sie James DiGioia , JS Choi oder Daniel Ehrenberg auf Twitter folgen .


Aber was noch wichtiger ist: Sobald die Arbeiten an der pipeline abgeschlossen sind, versuchen Sie es in Ihren Projekten! Wir arbeiten auch daran, repl neue Funktionen hinzuzufügen , damit Sie Ihren Code interaktiv überprüfen können. Wir brauchen Feedback, und die Verwendung in echtem Code hilft wirklich dabei, es zusammenzusetzen. Poste Tweets an @babeljs .

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


All Articles