Aventuras del operador de la tubería en babel @ 7


La versión babel@7.0.0-beta52 tiene un nuevo indicador de configuración requerido para el @babel/plugin-proposal-pipeline-operator , que rompe la compatibilidad con versiones anteriores del complemento. En este artículo, aprenderá qué es el operador de pipeline y por qué necesita configuración.


UPD: las tuberías inteligentes aparecieron en 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


Estado actual


Gilbert Garza , quien originalmente propuso el operador de pipeline , se propuso obtener una sintaxis simple para "cadenas ordenadas de llamadas de función en un estilo funcional legible". El operador de canalización se origina en lenguajes como F #, Hack, Elm, Elixir y otros, y cuando lo agrega a JavaScript, surgen dos cuestiones polémicas:


  • ¿Dónde y cómo usar marcadores de posición?
  • ¿Cómo debe async / await en una tubería?

Marcadores de posición


La primera pregunta fue planteada por Kevin Smith en este boleto , donde sugirió usar el estilo de tubería del lenguaje Hack . En Hack, se requieren marcadores de posición para cualquier lado derecho de la tubería, por ejemplo:


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

Tomamos como base que el marcador de posición se puede usar en cualquier expresión y contiene el valor del último paso de canalización. Este enfoque nos brinda flexibilidad y una amplia oportunidad para escribir expresiones.


La otra cara de la moneda es la complejidad del lenguaje debido a la adición de una nueva ficha. Hasta ahora, hemos elegido un hash ( # ), y aunque la discusión aún está abierta, cualquier token potencialmente tendrá intersecciones con otros usos. Por ejemplo, el hash también es utilizado por campos privados de la clase , al igual que cualquier otra variante de token.


Asíncrono / espera


La primera versión de la declaración de pipeline contenía esta sintaxis para await :


 x |> await f 

qué se puede implementar en:


 await f(x) 

Desafortunadamente, los usuarios pueden esperar tal implementación:


 (await f)(x) 

Si bien la idea misma de agregar async a la pipeline derrumbó, los miembros del comité se manifestaron en contra de un operador de pipeline que no admite async / await . Sí, hay opciones sobre cómo trabajar con funciones que devuelven Promise sin una sintaxis explícita, pero todas estas opciones son demasiado engorrosas o requieren funciones auxiliares.


Soluciones Sugeridas


Como resultado de las discusiones, se formaron dos propuestas (además de la opción mínima): usar F # -piplines y Smart-pipelines. Veamos estas sugerencias.


Opción de operador mínimo


Esta oferta se aplica solo a la funcionalidad básica. En la versión mínima, se elimina el soporte para la asincronía y no hay marcadores de posición. Esta opción corresponde al comportamiento del complemento de babel de versiones anteriores, antes de la aparición de la configuración, y corresponde a la especificación actual para el operador de la pipeline en el repositorio. Se usa más como un proyecto de investigación para identificar las ventajas y desventajas de otras propuestas, y es poco probable que sea aceptado sin los cambios fundamentales que se encuentran en las propuestas alternativas.


F # tuberías


Los marcadores de posición para tuberías F # no son necesarios en absoluto. En la versión básica, las funciones de flecha cubren la necesidad de marcadores de posición, que requieren menos garabatos, y se basan en la sintaxis ES2015 familiar para todos.


En este momento (de acuerdo con la especificación de las líneas F #), las funciones de flecha deben estar entre paréntesis:


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

Se están realizando encuestas para determinar si es factible utilizar funciones de flecha sin paréntesis, que aquí parecen sintácticamente redundantes.


En cuanto a la asincronía, await funciona como una función unaria en las tuberías de F #:


 promise |> await 

Lo que se desarrolla en:


 await promise 

y, por lo tanto, await se puede usar en medio de una larga cadena de llamadas asincrónicas:


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

Tal procesamiento de await especial puede potencialmente abrir la posibilidad de utilizar de manera similar otros operadores unarios (por ejemplo, typeof ), pero la especificación original de tuberías F # no los contiene.


Tuberías inteligentes


Las tuberías de Smar llevan la idea de los marcadores de posición a su conclusión lógica, permitiendo tanto el uso parcial como las expresiones arbitrarias en las tuberías. La cadena larga anterior se puede escribir así:


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

Las reglas para usar marcadores de posición en tuberías inteligentes son bastante simples. Si se pasa un solo identificador al paso de canalización, entonces no se requiere un token adicional (marcador de posición), esto se denomina "estilo simple" :


 x |> a; x |> fb; 

A diferencia de Hack, las funciones unarias no requieren un token de marcador de posición.


Para otras expresiones, se requiere un marcador de posición (llamado "token de tema léxico"), y se considera que una tubería funciona dentro del "estilo de tema" - "estilo de tema" . La ausencia de un token de marcador de posición en este caso causa un error de SyntaxError temprano:


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

Si hay operadores, corchetes (incluso para llamar a un método), comillas o cualquier otra cosa, excepto un identificador y un punto, se requiere el token de marcador de posición. Esto ayudará a evitar recibir un disparo en el pie y eliminar la incertidumbre.


Las canalizaciones inteligentes resuelven el problema de admitir la asincronía de una manera más general, lo que nos permite utilizar todas las expresiones posibles en las canalizaciones, no solo en await , sino también en typeof , yield y cualquier otro operador.


Babel entra en escena


Tan pronto como se concretaron las tres propuestas, llegamos a la conclusión de que tales debates no conducirían a la resolución de profundas contradicciones entre las propuestas. Decidimos que la mejor manera es recopilar comentarios de los desarrolladores utilizando oraciones en código real. Dado el papel de Babel en la comunidad de desarrolladores, decidimos agregar las tres opciones al complemento del operador de pipeline .


Dado que el análisis de las tres oraciones es leve, pero diferente, su apoyo primero debe agregarse a @babel/parser (que es babylon ), y el analizador debe saber qué propuesta debe ser compatible ahora. Por lo tanto, el complemento de operador de pipeline requiere la opción "proposal" , tanto para configurar Babilonia para el análisis como para la transformación posterior.


Trabajamos en esto en línea porque necesitamos hacer todos los cambios rompiendo la compatibilidad con versiones anteriores antes de que babel @ 7 deje de ser beta. Al final, nos gustaría establecer una de las opciones de canalización predeterminadas para el complemento para eliminar la necesidad de una opción de configuración.


Dadas estas limitaciones, decidimos agregar una opción a la configuración del complemento y hacerla obligatoria, obligando a los usuarios a decidir cuál de las ofertas desean usar en su proyecto. Tan pronto como se elija una propuesta específica como el comportamiento canónico del operador, marcamos la opción "proposal" como obsoleta, y la opción canónica funcionará de manera predeterminada. El soporte para ofertas canceladas funcionará hasta la próxima versión principal.


Tomar parte


Si desea participar en la discusión de la propuesta, todas las discusiones son públicas y puede encontrarlas en el repositorio de la propuesta del operador de la tubería . Una presentación de la reunión TC39 también está a su servicio. Al final, puedes seguir a James DiGioia , JS Choi o Daniel Ehrenberg en Twitter.


Pero lo más importante, tan pronto como se complete el trabajo en la pipeline , ¡pruébelo en sus proyectos! También estamos trabajando para agregar nuevas funciones a las respuestas , para que pueda verificar su código de forma interactiva. Necesitamos comentarios, y usarlo en código real realmente ayudará a ensamblarlo. Publica tweets en @babeljs .

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


All Articles