Aventuras do operador de oleoduto em babel @ 7


A versão babel@7.0.0-beta52 possui um novo sinalizador de configuração necessário para o @babel/plugin-proposal-pipeline-operator application @babel/plugin-proposal-pipeline-operator , que quebra a compatibilidade com versões anteriores das versões anteriores do plugin. Neste artigo, você aprenderá o que é o operador de pipeline e por que ele precisa de configuração.


UPD: pipelines inteligentes apareceram em 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


Status atual


Gilbert Garza , que originalmente propôs o operador de pipeline , decidiu obter uma sintaxe simples para "cadeias ordenadas de chamadas de função em um estilo funcional legível". O operador de pipeline se origina em idiomas como F #, Hack, Elm, Elixir e outros, e quando você o adiciona ao JavaScript, surgem dois problemas controversos:


  • Onde e como usar espaços reservados?
  • Como async / await em um pipeline?

Espaços reservados


A primeira pergunta foi levantada por Kevin Smith neste ticket , onde ele sugeriu o uso do estilo de pipe da linguagem Hack . No Hack, os espaços reservados são necessários para qualquer lado direito do pipeline, por exemplo:


 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 o espaço reservado pode ser usado em qualquer expressão e contenha valor da última etapa do pipeline. Essa abordagem nos oferece flexibilidade e ampla oportunidade para escrever expressões.


O outro lado da moeda é a complexidade do idioma devido à adição de um novo token. Até agora, escolhemos um hash ( # ) e, embora a discussão ainda esteja aberta, qualquer token terá interseções com outros usos. Por exemplo, o hash também é usado por campos particulares da classe , assim como qualquer outra versão de token.


Assíncrono / aguardar


A primeira versão da instrução de pipeline continha esta sintaxe para await :


 x |> await f 

o que pode ser implantado para:


 await f(x) 

Infelizmente, os usuários podem esperar essa implantação:


 (await f)(x) 

Embora a própria idéia de adicionar async ao pipeline derrapado, os membros do comitê se manifestaram contra um operador de pipeline que não suporta async / await . Sim, existem opções para trabalhar com funções que retornam Promise sem sintaxe explícita, mas todas essas opções são muito complicadas ou requerem funções auxiliares.


Soluções sugeridas


Como resultado das discussões, duas propostas foram formadas (além da opção mínima): use linhas F # e linhas inteligentes. Vamos dar uma olhada nessas sugestões.


Opção mínima do operador


Esta oferta se aplica apenas à funcionalidade básica. Na versão mínima, o suporte à assincronia é removido e não há espaços reservados. Esta opção corresponde ao comportamento do plug-in babel das versões anteriores, antes da configuração ser exibida, e corresponde à especificação atual do operador de pipeline no repositório. Ele é usado mais como uma sonda preliminar para identificar as vantagens e desvantagens de outras propostas e é improvável que seja aceito sem as alterações fundamentais que existem em propostas alternativas.


Tubulações F #


Os espaços reservados para os pipelines F # não são necessários. Na versão básica, as funções de seta cobrem a necessidade de espaços reservados, exigindo menos rabiscos e são baseadas na sintaxe do ES2015, familiar a todos.


No momento (de acordo com a especificação das linhas F #), as funções das setas devem estar entre colchetes:


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

Pesquisas estão em andamento para determinar se é possível usar funções de seta sem parênteses, que parecem sintaticamente redundantes aqui.


Quanto à assincronia, o await funciona como uma função unária nos pipelines F #:


 promise |> await 

O que se desenrola em:


 await promise 

e, portanto, await pode ser usado no meio de uma longa cadeia de chamadas assíncronas:


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

Esse processamento especial de await pode potencialmente abrir a possibilidade de usar similarmente outros operadores unários (por exemplo, typeof ), mas a especificação original dos tubos F # não os contém.


Pipelines inteligentes


Os pipelines inteligentes levam a ideia dos espaços reservados à sua conclusão lógica, permitindo o uso parcial e expressões arbitrárias nos piplines. A cadeia longa anterior pode ser escrita assim:


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

As regras para o uso de espaços reservados em pipelines inteligentes são bastante simples. Se um único identificador for passado para a etapa do pipeline, nenhum token adicional (espaço reservado) será necessário, isso é chamado de "estilo simples" :


 x |> a; x |> fb; 

Diferentemente do Hack, funções unárias não exigem um token de espaço reservado.


Para outras expressões, um espaço reservado (chamado de “token de tópico lexical”) é necessário e um pipeline é considerado para trabalhar dentro do “estilo do tema” - “estilo do tópico” . A ausência de um token de espaço reservado nesse caso causa um erro SyntaxError anterior:


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

Se houver operadores, colchetes (inclusive para chamar um método), aspas ou qualquer outra coisa, exceto um identificador e um ponto, o token de espaço reservado será necessário. Isso ajudará a evitar um tiro no pé e a eliminar a incerteza.


Os pipelines inteligentes resolvem o problema de dar suporte à assincronia de uma maneira mais geral, o que nos permite usar todas as expressões possíveis nos pipelines, não apenas await , mas também o typeof yield e outros operadores.


Babel entra em cena


Assim que as três propostas foram concretizadas, chegamos à conclusão de que essas discussões não levariam à resolução de profundas contradições entre as propostas. Decidimos que a melhor maneira é coletar feedback dos desenvolvedores usando frases em código real. Dado o papel de Babel na comunidade de desenvolvedores, decidimos adicionar todas as três opções ao plug-in do operador de pipeline .


Como a análise para as três frases é um pouco, mas diferente, o suporte deve primeiro ser adicionado ao @babel/parser (que é babylon ) e o analisador deve saber qual proposta deve ser suportada agora. Portanto, o plug-in do operador de pipeline requer a opção "proposal" , tanto para configurar o babylon para análise quanto para transformação subseqüente.


Nós trabalhamos nisso online porque precisamos fazer todas as alterações quebrando a compatibilidade com versões anteriores antes que o babel @ 7 deixe de ser beta. No final, gostaríamos de tornar uma das opções de pipeline padrão para o plug-in, a fim de nos livrar da necessidade de uma opção de configuração.


Dadas essas limitações, decidimos adicionar uma opção à configuração do plug-in e torná-la obrigatória, forçando os usuários a decidir qual das ofertas eles desejam usar em seu projeto. Assim que uma proposta específica é escolhida como o comportamento canônico do operador, marcamos a opção "proposal" como obsoleta, e a opção canônica funcionará por padrão. O suporte para ofertas canceladas funcionará até a próxima versão principal.


Participar


Se você deseja participar da discussão da proposta, todas as discussões são públicas e você pode encontrá-las no repositório da proposta do operador de pipeline . Uma apresentação da reunião do TC39 também está à sua disposição. No final, você pode seguir James DiGioia , JS Choi ou Daniel Ehrenberg no Twitter.


Mais importante, porém, assim que o trabalho no pipeline for concluído, experimente-o em seus projetos! Também estamos trabalhando para adicionar novos recursos ao repl , para que você possa verificar seu código interativamente. Precisamos de feedback, e usá-lo em código real realmente ajudará a montá-lo. Poste tweets em @babeljs .

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


All Articles