Posso usar a sintaxe da função de seta do ES6 com geradores? (notação de seta)

242

ou seja, como eu expresso isso:

function *(next) {}

com flechas. Eu tentei todas as combinações em que consegui pensar e não consigo encontrar nenhuma documentação.

(atualmente usando o nó v0.11.14)

Ashley Coolman
fonte
5
Você não pode. Desculpe. "A function*declaração (palavra-chave da função seguida por um asterisco) define uma função do gerador."
2
Observe que houve uma discussão bastante demorada sobre esse tópico no esdiscuss.org .
voithos
4
O que você espera param*=>{ }fazer?
CoderPi
4
você sabe que function(){}não está fazendo o mesmo que ()=>{}?
CoderPi
8
" É realmente que os geradores ES6 são 2 passos à frente e um passo para trás? " - não, geradores só pode avançar :-)
Bergi

Respostas:

230

Posso usar a sintaxe da função de seta do ES6 com geradores?

Você não pode. Desculpe.

De acordo com a MDN

A function*instrução ( functionpalavra-chave seguida por um asterisco) define uma função geradora.

De um documento de especificação (minha ênfase):

A sintaxe da função é estendida para adicionar um *token opcional :

FunctionDeclaration: "function" "*"? Identifier "(" FormalParameterList? ")" 
  "{" FunctionBody "}"

fonte
174
Parece uma falha de design para mim.
21915 Jonathon
23
@ Jonathon: Não. As funções de seta devem ser leves (e não têm, .prototypepor exemplo) e, geralmente, de uma linha, enquanto os geradores são praticamente o oposto.
Bergi
38
Eu já deparei com alguns cenários em que um gerador com o qual eu estava jogando precisava de acesso ao anterior thise tive que escrever o let self = thishack para ter acesso a ele dentro do gerador. O escopo lexical + sintaxe da seta teria sido bom. Infeliz, mas não exatamente o fim do mundo.
precisa
3
Alguns contexto adicional em torno deste em esdiscuss
Nick Tomlin
20
@ Bergi, o raciocínio por trás das funções das setas é muito mais complicado do que isso. Não é realmente uma questão de brevidade. As funções de seta não precisam ser leves - é verdade que existe uma sintaxe opcional do corpo de instrução única, mas e daí? Muitas pessoas usam setas para todas as definições de função, exceto os métodos de classe, e rebaixam a functionpalavra-chave por ser uma "parte ruim" da linguagem. Existem boas razões para fazer isso. Para essas pessoas, a falta de geradores de flechas é uma inconsistência irritante.
Callum #
130

A diferença entre funções Inline e funções Arrow

Antes de tudo , as funções Arrow () => {} não são feitas para substituir as funções Inline function(){}e são diferentes. Funções inline são simplesmente funções, então a questão é qual é a diferença entre as funções Arrow e as funções inline.

Uma expressão função seta (também conhecida como função de seta) tem uma sintaxe mais curta em comparação com a expressão de função e não se liga a sua própria this, arguments, super, ou new.target). As funções de seta são sempre anônimas.

Alguns detalhes mais rápidos aqui


Por que a função Arrow não pode ser usada como geradores

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Uso da palavra-chave yield

A palavra-chave yield não pode ser usada no corpo de uma função de seta (exceto quando permitido em funções ainda mais aninhadas). Como conseqüência, as funções de seta não podem ser usadas como geradores.

Note que geradores sem yieldnão fazem sentido.


Por que a função Arrow não pode usar rendimento

http://tc39wiki.calculist.org/es6/arrow-functions/

As funções de seta são vinculadas thislexicamente, vinculadas returnno caso do corpo do Bloco , para que retornem da função de seta imediatamente envolvente e impedem breake continuede fazer referência a instruções fora da função de seta imediatamente envolvente.

A expressão primária Identifierarguments não pode ser usada no corpo de uma função de seta (seja expressão ou forma de bloco).

Da mesma forma, yieldnão pode ser usado no corpo de uma função de seta. As setas não podem ser geradoras e não queremos continuações profundas.

O rendimento em uma função de seta gerará erro semântico: http://www.ecma-international.org/

No final, o motivo está na profunda complexidade na implementação do ECMA6. O C # não permite isso também por razões um tanto semelhantes .

CoderPi
fonte
3
Eu usei um mecanismo de pesquisa e
publiquei
1
Eu ainda acho que adicionar explicações sobre ()=>{}ajudaria muito, entender sua diferença de uma função em linha e por que a limitação existe para os geradores.
precisa saber é o seguinte
63
Eu estou tentando descobrir por que *() => { yield bla; }não é ok, mas async () => { await bla; }é ...
Lee Benson
7
@CodeiSir, Re " e não queremos continuações profundas ", desculpas ruins.
Pacerier
9
Seu argumento é cíclico. Você diz que as funções de seta não podem ser geradoras porque não podem ter a palavra-chave yield. Mas eles não podem ter a palavra-chave yield, porque não podem ser geradores: "As setas não podem ser geradoras e não queremos continuações profundas".
Thayne
35

Além da discussão em esdiscuss.org e das notas de reunião ES6 do comitê Ecma TC39 de novembro de 2013 mencionadas acima, as setas do gerador foram revisadas em duas reuniões ES7 de setembro de 2016 [1] [2] . Após uma discussão sobre prós e contras de várias sintaxes (principalmente =*>e =>*) e uma falta de justificativas e casos de uso para esse recurso, eles chegaram à conclusão de que:

  • Há algum interesse do comitê, mas a preocupação é que o recurso não contribua para adicionar uma nova parte da sintaxe
  • Planeje revisitar no dia 3 para ver se podemos chegar =>*ao estágio 0, pelo menos, como parte da proposta de iteração assíncrona de [Domenic Denicola]

A proposta de flechas geradoras foi movida para o Estágio 1, com Brendan Eich e Domenic Denicola como campeões. A iteração assíncrona mencionada acima foi concluída e implementada em 2018.

Em outubro de 2019, um repo oficial de Sergey Rubanov apareceu com mais discussão sobre sintaxe e outros detalhes.

tempo monge
fonte
8

Eu também estava tendo a mesma pergunta e vim aqui. Depois de ler as postagens e comentários, senti que usar o gerador em uma função de seta parece ser vago:

const generator = () => 2*3; // * implies multiplication
// so, this would be a confusing
const generator = () =>* something; // err, multiplying?
const generator = () =*> ... // err, ^^
const generator = ()*=> ... // err, *=3, still multiplying?
const generator=*()=> ... // err, ^^
const generator = *param => ... //err, "param" is not fixed word

Este é o motivo pelo qual eles não implementaram o gerador em relação à função de seta.


Mas, se eu fosse um deles, poderia ter pensado assim:

const generator = gen param => ... // hmm, gen indicates a generator
const generator = gen () => ... // ^^

Parece que temos a função assíncrona:

const asyncFunction = async () => ... // pretty cool

Como, com a função normal, a palavra - chave assíncrona existe, a função de seta a está utilizando - async () =>é provável que pareça async function().

Mas, não existe palavra-chave como genou generatore, infelizmente, a função de seta não a está usando.

Concluir:

Mesmo que eles desejem implementar o gerador na função de seta, acho que precisam repensar a sintaxe do gerador no núcleo js:

generator function myfunc() {}
// rather than
function* myfunc() {} // or, function *myfunc() {}

E isso será um grande erro. Portanto, manter a função da seta fora do gerador é muito legal.


Seguindo o comentário da @Bergi :

Não. As funções de seta devem ser leves (e não possuem um protótipo, por exemplo) e, geralmente, uma linha, enquanto os geradores são praticamente o oposto.

Eu direi que o propósito do gerador a ser usado é executar, parar, executar e, portanto, acho que não precisamos nos preocupar com protótipos, lexicais, etc.

Bhojendra Rauniyar
fonte
2
Também poderia considerar opções exóticas também () ~> { yield 'a'; yield 'b'; }. Para ser sincero, adoro tildes.
Gershom
@Gershom É assim que linguagens de programação como Perl dão totalmente errado
Sapphire_Brick
2

Eu sei que isso é muito tarde, mas outro possível motivo pode ser a sintaxe. talvez (*() => {})funcione, mas e quanto (9 ** () => {})? Isso é 9 ao poder de uma função de seta, retornando NaN, ou 9 vezes uma função de seta de gerador, também retornando NaN? Isso poderia ser feito com alguma sintaxe alternativa, como =>*mencionado em outra resposta aqui, mas talvez houvesse um desejo de preservar a consistência da sintaxe da função do gerador (por exemplo, function* () {}e { *genMethod() {} }) quando ela estava sendo implementada. Não é uma desculpa demais, mas uma razão para isso.

coolreader18
fonte
1
: +1: para os asteriscos duplos ... Cara da velha escola JS aqui. Quem disse que você não pode ensinar um cachorro velho novos truques: alegria:
Shanimal
A única razão pela qual eles não fazem isso é porque é difícil fazer o analisador. É inteiramente possível e não requer compromisso na sintaxe.
21419 Jason McMarrell
@JasonMcCarrell Se eles se importaram o suficiente em não tornar o analisador muito complexo, talvez Brendan Eich devesse ter colocado o Scheme no navegador.
Sapphire_Brick
1

No momento, você não pode, mas no futuro pode ser porque a TC39 libera a proposta para o mesmo em outubro de 2019, que está no estágio 1.

Gourav Makhija
fonte
-4

Existe uma boa solução alternativa com redux-saga

import { call, all } from 'redux-saga/effects';

function* gen() {
   yield all([].map(() => {
      return call(....);
   }));
}
Julius Baltrušaitis
fonte
4
Como sabemos que o OP está usando o Redux?
Maros