Kann ich die Pfeilfunktionssyntax von ES6 mit Generatoren verwenden? (Pfeilnotation)

242

dh wie drücke ich das aus:

function *(next) {}

mit Pfeilen. Ich habe alle erdenklichen Kombinationen ausprobiert und kann keine Dokumentation dazu finden.

(verwendet derzeit den Knoten v0.11.14)

Ashley Coolman
quelle
5
Das kannst du nicht. Es tut uns leid. "Die function*Anweisung (Funktionsschlüsselwort gefolgt von einem Sternchen) definiert eine Generatorfunktion."
2
Beachten Sie, dass es auf esdiscuss.org eine etwas längere Diskussion zu diesem Thema gab .
Voithos
4
Was erwartest du param*=>{ }zu tun?
CoderPi
4
Sie wissen, dass function(){}das nicht dasselbe tut wie ()=>{}?
CoderPi
8
"
Ist

Antworten:

230

Kann ich die Pfeilfunktionssyntax von ES6 mit Generatoren verwenden?

Das kannst du nicht. Es tut uns leid.

Laut MDN

Die function*Anweisung ( functionSchlüsselwort gefolgt von einem Sternchen) definiert eine Generatorfunktion.

Aus einem Spezifikationsdokument (mein Schwerpunkt):

Die Funktionssyntax wird um ein optionales *Token erweitert:

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

quelle
173
Fühlt sich für mich wie ein Designfehler an.
Jonathon
23
@ Jonathon: Nein. Pfeilfunktionen sollen leicht sein (und haben .prototypezum Beispiel keine ) und oft Einzeiler, während Generatoren so ziemlich das Gegenteil sind.
Bergi
38
Ich bin bereits auf einige Szenarien gestoßen, in denen ein Generator, mit dem ich gespielt habe, Zugriff auf den vorherigen benötigte this, und musste den let self = thisHack schreiben , um im Generator darauf zugreifen zu können. Die lexikalische Scope + Pfeil-Syntax wäre schön gewesen. Leider, aber nicht gerade das Ende der Welt.
dvlsg
3
Einige zusätzliche Zusammenhänge dazu bei esdiscuss
Nick Tomlin
20
@Bergi Die Argumentation hinter Pfeilfunktionen ist viel komplizierter. Es geht nicht wirklich um Kürze. Pfeilfunktionen müssen nicht leicht sein - es gibt zwar eine optionale Körpersyntax mit einer Anweisung, aber na und. Viele Leute verwenden Pfeile für alle Funktionsdefinitionen mit Ausnahme von Klassenmethoden und stufen das functionSchlüsselwort als "schlechten Teil" der Sprache herab . Dafür gibt es gute Gründe. Für diese Menschen ist das Fehlen von Pfeilgeneratoren eine ärgerliche Inkonsistenz.
Callum
130

Der Unterschied zwischen Inline-Funktionen und Pfeilfunktionen

Vor allem Pfeil-Funktionen () => {} sind nicht zu ersetzen , Inline-Funktionen gemacht function(){}und sie sind unterschiedlich. Inline-Funktionen sind einfach Funktionen, daher stellt sich die Frage, was der Unterschied zwischen Pfeilfunktionen und Inline-Funktionen ist.

Ein Pfeil Funktionsausdruck (auch als Pfeilfunktion bekannt) hat eine kürzere Syntax im Vergleich zu Funktionsausdrücken und bindet nicht seine eigene this, arguments, super, oder new.target). Pfeilfunktionen sind immer anonym.

Einige schnellere Details hier


Warum die Pfeilfunktion nicht als Generatoren verwendet werden kann

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

Verwendung des Schlüsselwortsield

Das Schlüsselwort yield darf nicht im Hauptteil einer Pfeilfunktion verwendet werden (es sei denn, dies ist in Funktionen zulässig, die weiter darin verschachtelt sind). Folglich können Pfeilfunktionen nicht als Generatoren verwendet werden.

Beachten Sie, dass Generatoren ohne yieldkeinen Sinn ergeben.


Warum die Pfeilfunktion keine Ausbeute verwenden kann

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

Pfeilfunktionen binden thislexikalisch, binden returnim Block Fall, sodass sie von der unmittelbar einschließenden Pfeilfunktion zurückkehren breakund continueAnweisungen außerhalb der unmittelbar einschließenden Pfeilfunktion ausschließen und darauf verweisen.

Das primäre Ausdruck " Bezeichner"arguments darf nicht im Hauptteil einer Pfeilfunktion verwendet werden (ob Ausdruck oder Blockform).

Gleichfalls, yield darf nicht im Körper einer Pfeilfunktion verwendet werden. Pfeile können keine Generatoren sein und wir wollen keine tiefen Fortsetzungen.

Die Ausbeute in einer Pfeilfunktion löst einen semantischen Fehler aus: http://www.ecma-international.org/

Am Ende liegt der Grund in der tiefen Komplexität bei der Implementierung von ECMA6. C # erlaubt dies aus ähnlichen Gründen ebenfalls nicht .

CoderPi
quelle
3
Ich habe eine Suchmaschine verwendet und eine weitere Erklärung für Sie veröffentlicht
CoderPi
1
Ich denke immer noch, dass das Hinzufügen von Erklärungen ()=>{}viel dazu beitragen würde, den Unterschied zu einer Inline-Funktion zu verstehen und warum die Einschränkung für Generatoren besteht.
Vitaly-t
63
Ich versuche herauszufinden, warum *() => { yield bla; }es nicht in Ordnung ist, aber async () => { await bla; }...
Lee Benson
7
@CodeiSir, Re " und wir wollen keine tiefen Fortsetzungen ", miese Ausreden.
Pacerier
9
Ihr Argument ist zyklisch. Sie sagen, dass Pfeilfunktionen keine Generatoren sein können, weil sie nicht das Schlüsselwort yield enthalten können. Aber sie können das Schlüsselwortield nicht haben, weil sie keine Generatoren sein können: "Pfeile können keine Generatoren sein und wir wollen keine tiefen Fortsetzungen."
Thayne
35

Zusätzlich zu der oben erwähnten Diskussion auf esdiscuss.org und den ES6-Sitzungsnotizen des Ecma TC39-Ausschusses vom November 2013 wurden die Generatorpfeile in zwei ES7-Sitzungen im September 2016 erneut überprüft [1] [2] . Nach einer Diskussion über Vor- und Nachteile verschiedener Syntax (hauptsächlich =*>und =>*) und einem Mangel an Begründungen und Anwendungsfällen für diese Funktion kamen sie zu dem Schluss, dass:

  • Das Komitee hat ein gewisses Interesse, befürchtet jedoch, dass das Feature beim Hinzufügen einer neuen Syntax nicht an Bedeutung gewinnt
  • Planen Sie einen =>*erneuten Besuch an Tag 3, um zu sehen, ob wir im Rahmen des Async-Iterationsvorschlags von [Domenic Denicola] mindestens Stufe 0 erreichen können

Der Vorschlag für Generatorpfeile wurde mit Brendan Eich und Domenic Denicola als Champions auf Stufe 1 verschoben. Die oben erwähnte asynchrone Iteration wurde beendet und implementiert 2018 .

Im Oktober 2019 erschien ein offizielles Repo von Sergey Rubanov mit weiteren Diskussionen über Syntax und andere Details.

Mönchszeit
quelle
8

Ich hatte auch die gleiche Frage und kam hierher. Nachdem ich die Beiträge und Kommentare gelesen hatte, fühlte ich, dass die Verwendung des Generators in einer Pfeilfunktion vage zu sein scheint:

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

Dies ist möglicherweise der Hauptgrund dafür, dass der Generator in Bezug auf die Pfeilfunktion nicht implementiert wurde.


Aber wenn ich einer von ihnen wäre, hätte ich so denken können:

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

Das fühlt sich so an, als hätten wir eine asynchrone Funktion:

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

Da bei normaler Funktion das asynchrone Schlüsselwort vorhanden ist, wird es von der Pfeilfunktion verwendet - async () =>wahrscheinlichasync function() .

Es gibt jedoch kein Schlüsselwort wie genodergenerator und leider verwendet die Pfeilfunktion es nicht.

Schlussfolgern:

Selbst wenn sie den Generator in der Pfeilfunktion implementieren möchten, müssen sie die Generatorsyntax in Kern js überdenken:

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

Und das wird ein großer Fehler sein. Es ist also ziemlich cool, die Pfeilfunktion vom Generator fernzuhalten.


Folgender @Bergi Kommentar :

Nein. Pfeilfunktionen sollen leicht sein (und zum Beispiel keinen Prototyp haben) und oft einzeilig, während Generatoren so ziemlich das Gegenteil sind.

Ich werde sagen, dass der zu verwendende Generatorzweck Run-Stop-Run ist, und daher denke ich nicht, dass wir uns um Prototypen, Lexika usw. kümmern müssen.

Bhojendra Rauniyar
quelle
2
Könnte auch exotische Optionen in Betracht ziehen, wie z () ~> { yield 'a'; yield 'b'; }. Um ehrlich zu sein, ich liebe Tildes.
Gershom
@Gershom So gehen Programmiersprachen wie Perl völlig schief
Sapphire_Brick
2

Ich weiß, dass dies sehr spät ist, aber ein weiterer möglicher Grund könnte die Syntax sein. (*() => {})funktioniert vielleicht , aber was ist mit (9 ** () => {})? Ist das 9 hoch einer Pfeilfunktion, die zurückkehrt NaN, oder ist es 9 mal eine Generatorpfeilfunktion, die ebenfalls zurückkehrt NaN? Dies könnte mit einer alternativen Syntax erfolgen, wie =>*in einer anderen Antwort hier erwähnt, aber möglicherweise bestand der Wunsch, die Konsistenz der Generatorfunktionssyntax (z. B. function* () {}und { *genMethod() {} }) bei der Implementierung beizubehalten. Keine allzu große Entschuldigung, aber ein Grund dafür.

coolreader18
quelle
1
: +1: für die doppelten Sternchen ... Alter JS-Typ hier. Wer sagt, dass Sie einem alten Hund keine neuen Tricks beibringen können: Freude:
Shanimal
Der einzige Grund, warum sie es nicht tun, ist, dass es schwierig ist, den Parser zu erstellen. Dies ist durchaus möglich und erfordert keine Kompromisse bei der Syntax.
Jason McCarrell
@JasonMcCarrell Wenn es ihnen wichtig genug war, den Parser nicht zu komplex zu machen, hätte Brendan Eich Scheme vielleicht in den Browser stellen sollen.
Sapphire_Brick
1

Im Moment können Sie nicht, aber in Zukunft könnten Sie sein, weil TC39 Release- Vorschlag für das gleiche im Oktober 2019, das sich in Stufe 1 befindet.

Gourav Makhija
quelle
-4

Es gibt eine schöne Problemumgehung mit Redux-Saga

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

function* gen() {
   yield all([].map(() => {
      return call(....);
   }));
}
Julius Baltrušaitis
quelle
4
Woher wissen wir, dass OP Redux verwendet?
Maros