Czy mogę używać składni funkcji strzałek ES6 w generatorach? (notacja ze strzałką)

243

tj. jak to wyrazić:

function *(next) {}

ze strzałkami. Wypróbowałem wszystkie kombinacje, jakie mogłem wymyślić, i nie mogę znaleźć na to żadnej dokumentacji.

(obecnie używa węzła v0.11.14)

Ashley Coolman
źródło
5
Nie możesz Przepraszam. „ function*Instrukcja (słowo kluczowe funkcji, po której następuje gwiazdka) definiuje funkcję generatora.”
2
Zauważ, że odbyła się dość długa dyskusja na ten temat na stronie esdiscuss.org .
voithos
4
Czego oczekujesz param*=>{ }zrobić?
CoderPi
4
wiesz, że function(){}to nie robi tego samego co ()=>{}?
CoderPi
8
czy to naprawdę, że generatory ES6 są 2 kroki do przodu i 1 do tyłu? ” - nie, generatory mogą tylko krok do przodu :-)
Bergi

Odpowiedzi:

231

Czy mogę używać składni funkcji strzałek ES6 w generatorach?

Nie możesz Przepraszam.

Według MDN

function*Oświadczenie ( functionsłowo kluczowe, a następnie gwiazdką) definiuje funkcję generatora.

Z dokumentu specyfikacji (moje podkreślenie):

Funkcja składnia jest przedłużony, aby dodać opcjonalny *znak:

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

źródło
175
Wydaje mi się, że to wada projektowa.
Jonathon
23
@Jonathon: Nie. Funkcje strzałek powinny być lekkie (i nie mają .prototypena przykład) i często jednowarstwowe, podczas gdy generatory są wręcz przeciwne.
Bergi
38
Natknąłem się już na kilka scenariuszy, w których grałem z generatorem, który potrzebował dostępu do poprzedniego thisi musiałem napisać let self = thishack, aby uzyskać dostęp do niego w generatorze. Przydałby się zakres leksykalny + składnia strzałki. Niestety, ale nie do końca świata.
dvlsg
3
Dodatkowy kontekst wokół tego na esdiscuss
Nick Tomlin,
20
@Bergi uzasadnienie funkcji strzałek jest o wiele bardziej skomplikowane. Tak naprawdę nie chodzi o zwięzłość. Funkcje strzałek nie muszą być lekkie - to prawda, że ​​istnieje opcjonalna składnia pojedynczego wyrażenia, ale co z tego. Wiele osób używa strzałek do wszystkich definicji funkcji, z wyjątkiem metod klas, i obniża to functionsłowo kluczowe jako „złą część” języka. Są ku temu dobre powody. Dla tych osób brak generatorów strzał jest denerwującą niekonsekwencją.
callum
131

Różnica między funkcjami Inline i Arrow

Po pierwsze, funkcje strzałek () => {} nie są zastępowane funkcjami Inline function(){}i są różne. Funkcje Inline to po prostu Funkcje, więc pytanie brzmi, jaka jest różnica między funkcjami Strzałki a Funkcjami Inline.

Wyrażenie funkcja strzałka (znany również jako funkcja strzałka) ma krótszy w porównaniu do składni wyrażeń funkcyjnych i nie wiąże jej własny this, arguments, super, lub new.target). Funkcje strzałek są zawsze anonimowe.

Kilka szybkich szczegółów tutaj


Dlaczego funkcja strzałki nie może być używana jako generator?

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

Zastosowanie słowa kluczowego wydajności

Wydajność kluczowe nie mogą być stosowane w organizmie funkcję strzały (z wyjątkiem gdy jest to dozwolone w ciągu dalszych funkcji zagnieżdżonych w sobie). W rezultacie funkcje strzałek nie mogą być używane jako generatory.

Zauważ, że generatory bez yieldnie mają sensu.


Dlaczego funkcja strzałki nie może wykorzystywać wydajności

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

Funkcje strzałek wiążą się thisleksykalnie, wiążą returnw przypadku bryły bloku, więc wraca z bezpośrednio otaczającej funkcji strzałki i wyklucza breaki continueodwołuje się do instrukcji poza bezpośrednio otaczającą funkcją strzałki.

Identyfikator podstawowej ekspresji argumentsmogą być stosowane w ciele funkcji strzały (czy ekspresja lub w postaci bloku).

Podobnie, yieldnie może być stosowany w treści funkcji strzałki. Strzały nie mogą być generatorami i nie chcemy głębokich kontynuacji.

Wydajność w funkcji strzałki spowoduje wygenerowanie błędu semantycznego: http://www.ecma-international.org/

Ostatecznie przyczyną jest głęboka złożoność wdrażania ECMA6. C # nie pozwala na to również z nieco podobnych powodów .

CoderPi
źródło
3
Użyłem wyszukiwarki i zamieściłem dla ciebie jeszcze jedno Wyjaśnienie
CoderPi
1
Nadal uważam, że dodanie wyjaśnień na temat ()=>{}bardzo pomogłoby, aby zrozumieć różnicę w stosunku do funkcji wbudowanej i dlaczego istnieją ograniczenia dla generatorów.
vitaly-t
63
Próbuję dowiedzieć się, dlaczego *() => { yield bla; }nie jest dobrze, ale async () => { await bla; }jest ...
Lee Benson
7
@CodeiSir, Re „ i nie chcemy głębokich kontynuacji ”, kiepskie wymówki.
Pacerier
9
Twój argument jest cykliczny. Mówisz, że funkcje strzałek nie mogą być generatorami, ponieważ nie mogą zawierać słowa kluczowego fed. Ale nie mogą mieć słowa kluczowego określającego wydajność, ponieważ nie mogą być generatorami: „Strzałki nie mogą być generatorami i nie chcemy głębokich kontynuacji”.
Thayne,
35

Oprócz dyskusji na stronie esdiscuss.org i notatkach ES6 komitetu Ecma TC39 z listopada 2013 r. Wspomnianych powyżej, strzałki generatora zostały ponownie sprawdzone podczas dwóch spotkań ES7 we wrześniu 2016 r. [1] [2] . Po dyskusji na temat zalet i wad różnych składni (głównie =*>i =>*) oraz braku uzasadnień i przypadków użycia tej funkcji, doszli do wniosku, że:

  • Komitet cieszy się pewnym zainteresowaniem, ale obawia się, że funkcja nie pociąga za sobą znaczenia dodania nowej składni
  • Zaplanuj =>*ponowną wizytę w Dniu 3, aby zobaczyć, czy uda nam się przejść do etapu 0 przynajmniej w ramach propozycji iteracji asynchronicznej [Domenic Denicola]

Propozycja strzał generatora została przeniesiona na Etap 1 z Brendan Eich i Domenic Denicola jako mistrzami.Wspomniana iteracja asynchroniczna została zakończona i wdrożona w 2018 r.

W październiku 2019 r. Pojawiło się oficjalne repozytorium Siergieja Rubanowa z dalszą dyskusją na temat składni i innych szczegółów.

czas mnicha
źródło
8

Miałem też to samo pytanie i przyszedłem tutaj. Po przeczytaniu postów i komentarzy poczułem, że używanie generatora w funkcji strzałki wydaje się niejasne:

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

To może być główny powód, dla którego nie zaimplementowali generatora w związku z funkcją strzałki.


Ale gdybym był jednym z nich, pomyślałbym tak:

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

Wydaje się, że mamy funkcję asynchroniczną:

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

Ponieważ przy normalnej funkcji istnieje słowo kluczowe asynchroniczne , więc funkcja strzałki korzysta z niego - async () =>prawdopodobnie się wydaje async function().

Ale nie ma słowa kluczowego takiego jak genlub generatori, niestety, funkcja strzałki nie używa go.

Podsumowując:

Nawet jeśli chcą zaimplementować generator w funkcji strzałki, myślę, że muszą przemyśleć składnię generatora w rdzeniu js:

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

A to będzie wielka pomyłka. Tak więc utrzymywanie funkcji strzałki poza generatorem jest całkiem fajne.


Po komentarzu @Bergi :

Nie. Funkcje strzałek powinny być lekkie (i nie mają na przykład prototypu) i często jednowarstwowe, podczas gdy generatory są wręcz przeciwne.

Powiem, że celem generatora jest Run-Stop-Run, więc nie sądzę, że musimy dbać o prototyp, leksykalne itp.

Bhojendra Rauniyar
źródło
2
Można również rozważyć egzotyczne opcje, takie jak () ~> { yield 'a'; yield 'b'; }. Szczerze mówiąc, po prostu uwielbiam tyldy.
Gershom
@Gershom W ten sposób języki programowania, takie jak Perl, idą całkowicie nie tak
Sapphire_Brick
2

Wiem, że jest bardzo późno, ale innym możliwym powodem może być składnia. może (*() => {})działa, ale co z tym (9 ** () => {})? Czy to 9 do potęgi funkcji strzałki, powracającej NaN, czy też 9-krotność funkcji strzałki generatora, również powracającej NaN? Można to zrobić za pomocą jakiejś alternatywnej składni, jak =>*wspomniano w innej odpowiedzi tutaj, ale być może istnieje potrzeba zachowania spójności składni funkcji generatora (np. function* () {}I { *genMethod() {} }) podczas jej implementacji. Nie za wymówka, ale powód.

coolreader18
źródło
1
: +1: za podwójne gwiazdki ... Facet ze starej szkoły JS tutaj. Kto powiedział, że nie możesz nauczyć starego psa nowych sztuczek: radość:
Shanimal,
Jedynym powodem, dla którego tego nie robią, jest to, że utworzenie parsera jest trudne. Jest to całkowicie możliwe i nie wymaga kompromisu w składni.
Jason McCarrell
@JasonMcCarrell Jeśli zależy im na tym, aby parser nie był zbyt skomplikowany, być może Brendan Eich powinien umieścić Scheme w przeglądarce.
Sapphire_Brick
1

W tej chwili nie możesz, ale w przyszłości może tak być, ponieważ propozycja wydania TC39 na to samo w październiku 2019 r., Która jest na etapie 1.

Gourav Makhija
źródło
-4

Jest przyjemne obejście z saga redux

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

function* gen() {
   yield all([].map(() => {
      return call(....);
   }));
}
Julius Baltrušaitis
źródło
4
Skąd wiemy, że OP używa Redux?
Maros