¿Puedo usar la sintaxis de la función de flecha de ES6 con generadores? (notación de flecha)

243

es decir, cómo expreso esto:

function *(next) {}

con flechas He probado todas las combinaciones que se me ocurren, y no puedo encontrar ninguna documentación al respecto.

(actualmente usando el nodo v0.11.14)

Ashley Coolman
fuente
55
No puedes Lo siento. "La function*declaración (palabra clave de función seguida de un asterisco) define una función generadora".
2
Tenga en cuenta que hubo una discusión bastante larga sobre este tema en esdiscuss.org .
voithos
44
¿Qué esperas param*=>{ }hacer?
CoderPi
44
sabes que function(){}no está haciendo lo mismo que ()=>{}?
CoderPi
8
" ¿Es realmente tan generadores ES6 son 2 pasos hacia delante y hacia atrás 1 paso? " - no, generadores sólo pueden dar un paso adelante :-)
Bergi

Respuestas:

231

¿Puedo usar la sintaxis de la función de flecha de ES6 con generadores?

No puedes Lo siento.

De acuerdo con MDN

La function*declaración ( functionpalabra clave seguida de un asterisco) define una función generadora.

De un documento de especificaciones (mi énfasis):

La sintaxis de la función se extiende para agregar un *token opcional :

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

fuente
175
Se siente como un defecto de diseño para mí.
Jonathon
23
@Jonathon: No. Se supone que las funciones de flecha son livianas (y no tienen una, .prototypepor ejemplo) y, a menudo, de una sola línea, mientras que los generadores son todo lo contrario.
Bergi
38
Ya me he encontrado con algunos escenarios en los que un generador con el que estaba jugando necesitaba acceso al anterior this, y tuve que escribir el let self = thistruco para acceder dentro del generador. El alcance léxico + sintaxis de flecha hubiera sido bueno. Desafortunado, pero no exactamente el fin del mundo.
dvlsg
3
Algún contexto adicional sobre esto en esdiscuss
Nick Tomlin
20
@Bergi, el razonamiento detrás de las funciones de flecha es mucho más complicado que eso. No se trata realmente de brevedad. Las funciones de flecha no necesitan ser livianas; es cierto que hay una sintaxis opcional de cuerpo de una sola declaración, pero ¿y qué? Muchas personas usan flechas para todas las definiciones de funciones, excepto los métodos de clase, y degradan la functionpalabra clave para que sea una "parte mala" del lenguaje. Hay buenas razones para hacer esto. Para estas personas, la falta de generadores de flechas es una inconsistencia molesta.
callum
132

La diferencia entre las funciones en línea y las funciones de flecha

En primer lugar , las funciones de flecha () => {} no están hechas para reemplazar las funciones en línea function(){}y son diferentes. Las funciones en línea son simplemente funciones, por lo que la pregunta es cuál es la diferencia entre las funciones de flecha y las funciones en línea.

Una expresión de la función de flecha (también conocida como función de flecha) tiene una sintaxis más corta en comparación con las expresiones de función y no se une a su propia this, arguments, super, o new.target). Las funciones de flecha son siempre anónimas.

Algunos detalles más rápidos aquí


Por qué la función de flecha no se puede usar como generador

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

Uso de la palabra clave de rendimiento

La palabra clave de rendimiento no se puede usar en el cuerpo de una función de flecha (excepto cuando se permite dentro de funciones anidadas dentro de ella). Como consecuencia, las funciones de flecha no pueden usarse como generadores.

Tenga en cuenta que los generadores sin yieldno tienen sentido.


Por qué la función de flecha no puede usar el rendimiento

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

Las funciones de flecha se unen thisléxicamente, se unen returnen el caso del cuerpo del bloque para que regrese de la función de flecha que lo encierra inmediatamente, e impiden breaky hacen continuereferencia a declaraciones fuera de la función de flecha que lo encierra inmediatamente.

La expresión primaria Identificadorarguments no puede usarse en el cuerpo de una función de flecha (ya sea expresión o forma de bloque).

Del mismo modo, yieldno se puede usar en el cuerpo de una función de flecha. Las flechas no pueden ser generadores y no queremos continuas profundas.

El rendimiento en una función de flecha arrojará un error semántico: http://www.ecma-international.org/

Al final, la razón está en la profunda complejidad en la implementación de ECMA6. C # no permite esto también por razones algo similares .

CoderPi
fuente
3
Utilicé un motor de búsqueda y
publiqué
1
Sigo pensando que agregar explicaciones sobre ()=>{}ayudaría mucho, comprender su diferencia con respecto a una función en línea, y por qué la limitación existe para los generadores.
vitaly-t
63
Estoy tratando de averiguar por qué *() => { yield bla; }no está bien, pero async () => { await bla; }es ...
Lee Benson
77
@CodeiSir, Re " y no queremos continuas profundas ", pésimas excusas.
Pacerier
99
Tu argumento es cíclico. Usted dice que las funciones de flecha no pueden ser generadores porque no pueden tener la palabra clave de rendimiento en ellas. Pero no pueden tener la palabra clave de rendimiento, porque no pueden ser generadores: "Las flechas no pueden ser generadores y no queremos continuas profundas".
Thayne
36

Además de la discusión en esdiscuss.org y las notas de la reunión ES6 del comité Ecma TC39 de noviembre de 2013 mencionadas anteriormente, las flechas generadoras fueron revisadas en dos reuniones ES7 de septiembre de 2016 [1] [2] . Después de una discusión sobre los pros y los contras de varias sintaxis (principalmente =*>y =>*) y la falta de justificaciones y casos de uso para esta característica, llegaron a la conclusión de que:

  • Existe cierto interés por parte del comité, pero la preocupación de que la característica no ejerza su peso para agregar una nueva sintaxis
  • Planee volver a visitar el Día 3 para ver si podemos llegar =>*a la etapa 0 al menos, como parte de la propuesta de iteración asíncrona de [Domenic Denicola]

La propuesta de flechas generadoras se trasladó a la Etapa 1 con Brendan Eich y Domenic Denicola como campeones. La iteración asincrónica mencionada anteriormente se terminó e implementó en 2018.

En octubre de 2019 apareció un repositorio oficial de Sergey Rubanov con más discusión sobre la sintaxis y otros detalles.

tiempo de monje
fuente
8

También tenía la misma pregunta y vine aquí. Después de leer las publicaciones y los comentarios, sentí que usar el generador en una función de flecha 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

Esta es la razón por la que no implementaron el generador en relación con la función de flecha.


Pero, si fuera uno de ellos, podría haber pensado así:

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

Esto se siente como si tuviéramos una función asincrónica:

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

Porque, con la función normal, la palabra clave asíncrona existe, por lo que async () =>es probable que la función de flecha la esté utilizando async function().

Pero, no hay una palabra clave como geno generatory, por desgracia, la función de flecha no la está usando.

Para concluir:

Incluso si desean implementar el generador en la función de flecha, creo que necesitan repensar la sintaxis del generador en el núcleo js:

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

Y esto será un gran error. Por lo tanto, mantener la función de flecha fuera del generador es bastante bueno.


Siguiendo el comentario de @Bergi :

No. Se supone que las funciones de flecha son livianas (y no tienen un prototipo. Por ejemplo) y, a menudo, de una sola línea, mientras que los generadores son más o menos lo contrario.

Diré que el propósito del generador para usar es run-stop-run y, por lo tanto, no creo que debamos preocuparnos por el prototipo, esto léxico, etc.

Bhojendra Rauniyar
fuente
2
También podría considerar opciones exóticas, como () ~> { yield 'a'; yield 'b'; }. Para ser honesto, me encanta tildes.
Gershom
@Gershom Así es como los lenguajes de programación como Perl salen totalmente mal
Sapphire_Brick
2

Sé que esto es muy tarde, pero otra posible razón podría ser la sintaxis. tal vez (*() => {})funciona, pero ¿qué pasa (9 ** () => {})? ¿Eso es 9 a la potencia de una función de flecha, que regresa NaN, o es 9 veces una función de flecha del generador, que también regresa NaN? Podría hacerse con alguna sintaxis alternativa, =>*como se menciona en otra respuesta aquí, pero tal vez hubo un deseo de preservar la coherencia de la sintaxis de la función del generador (por ejemplo, function* () {}y { *genMethod() {} }) cuando se implementó. No es una gran excusa, sino una razón para ello.

coolreader18
fuente
1
: +1: para los dobles asteriscos ... el chico de la vieja escuela JS aquí. Quién dice que no puedes enseñarle a un perro viejo nuevos trucos: alegría:
Shanimal
La única razón por la que no lo hacen es porque hacer el analizador es difícil. Es completamente posible y no requiere compromiso en la sintaxis.
Jason McCarrell
@JasonMcCarrell Si se preocuparon lo suficiente por no hacer que el analizador sea demasiado complejo, entonces quizás Brendan Eich debería haber puesto Scheme en el navegador.
Sapphire_Brick
1

En este momento no puede, pero en el futuro podría ser debido a la propuesta de lanzamiento de TC39 para el mismo en octubre de 2019, que se encuentra en la etapa 1.

Gourav Makhija
fuente
-4

Hay una buena solución con redux-saga

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

function* gen() {
   yield all([].map(() => {
      return call(....);
   }));
}
Julius Baltrušaitis
fuente
44
¿Cómo sabemos que OP está usando Redux?
Maros