Могу ли я использовать синтаксис функции стрелки ES6 с генераторами? (обозначение стрелки)


243

т.е. как я могу выразить это:

function *(next) {}

со стрелками Я перепробовал все комбинации, которые мог придумать, и не могу найти никакой документации по этому вопросу.

(в настоящее время используется узел v0.11.14)


5
Ты не можешь Сожалею. « function*Оператор (ключевое слово функции, за которым следует звездочка) определяет функцию генератора».

2
Обратите внимание, что на эту тему было несколько продолжительное обсуждение на esdiscuss.org .
voithos

4
Что вы ожидаете param*=>{ }сделать?
CoderPi

4
Вы знаете, что function(){}не делает так же, как ()=>{}?
CoderPi

8
« Действительно ли генераторы ES6 на 2 шага вперед и на 1 шаг назад? » - нет, генераторы могут только шагать вперед :-)
Bergi

Ответы:


231

Могу ли я использовать синтаксис функции стрелки ES6 с генераторами?

Ты не можешь Сожалею.

По данным МДН

function*Утверждение ( functionключевое слово со звездочкой) определяет функцию генератора.

Из спецификации документа (мой акцент):

Функция синтаксис расширен , чтобы добавить дополнительный *маркер:

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

175
Похоже на недостаток дизайна для меня.
Джонатон

23
@Jonathon: Нет. Предполагается, что функции со стрелками должны быть легковесными (и не имеют, .prototypeнапример) и часто однострочными, в то время как генераторы в значительной степени противоположны.
Берги

38
Я уже сталкивался с несколькими сценариями, где генератор, с которым я играл, требовал доступа к предыдущему this, и мне пришлось написать let self = thisхак, чтобы получить доступ к нему внутри генератора. Синтаксис лексической области видимости + стрелки был бы хорош. К сожалению, но не совсем конец света.
dvlsg

3
Некоторый дополнительный контекст вокруг этого в esdiscuss
Ник Томлин

20
@ Берги, рассуждения о функциях стрелок намного сложнее, чем это. Дело не в краткости. Функции со стрелками не обязательно должны быть легковесными - это правда, есть необязательный синтаксис тела с одним оператором, ну и что с того. Многие люди используют стрелки для всех определений функций, кроме методов класса, и превращают functionключевое слово в «плохую часть» языка. Есть веские причины для этого. Для этих людей отсутствие стрелочных генераторов является досадным несоответствием.
Каллум

132

Разница между Inline-функциями и Arrow-функциями

Прежде всего Arrow-функции () => {} не предназначены для замены Inline-функций, function(){}и они разные. Inline-функции - это просто функции, поэтому вопрос в том, в чем разница между функциями Arrow и Inline-функциями.

Выражение функции стрелки (также известное как функция стрелки) имеет более короткий синтаксис по сравнению с выражениями функции и не связывает свое собственное this,arguments , super, или new.target). Функции стрелок всегда анонимны.

Еще несколько быстрых подробностей здесь


Почему Arrow-функция не может быть использована в качестве генератора

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

Использование ключевого слова yield

Выход ключевого слово не может быть использовано в теле функции стрелы (кроме случаев , когда разрешено в рамках функций дополнительно вложенных в него). Как следствие, функции стрелок не могут быть использованы в качестве генераторов.

Обратите внимание, что генераторы без yieldне имеют смысла.


Почему Arrow-функция не может использовать yield

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

Функции стрелок связывают thisлексически, связывают returnв корпусе блока, чтобы он возвращался из непосредственно включающей функции стрелки, и исключают breakи continueссылаются на операторы вне непосредственно включающей функции стрелки.

Идентификатор первичное выражениеarguments не может быть использовано в теле функцию стрелы (будь то выражение или блок - формы).

Кроме того, yieldне может использоваться в теле функции стрелки. Стрелки не могут быть генераторами, и мы не хотим глубоких продолжений.

Выход в функции со стрелкой вызовет семантическую ошибку: http://www.ecma-international.org/

В конце концов, причина кроется в глубокой сложности внедрения ECMA6. C # не допускает этого также по несколько схожим причинам .


3
Я использовал поисковую систему и опубликовал еще одно объяснение для вас
CoderPi

1
Я все еще думаю, что добавление объяснения ()=>{}очень помогло бы понять его отличие от встроенной функции, и почему существует ограничение для генераторов.
vitaly-t

63
Я пытаюсь выяснить, почему *() => { yield bla; }не в порядке, но async () => { await bla; }это ...
Ли Бенсон

7
@CodeiSir, Re " а мы не хотим глубоких продолжений ", паршивые оправдания.
Pacerier

9
Ваш аргумент цикличен. Вы говорите, что функции стрелок не могут быть генераторами, потому что в них не может быть ключевого слова yield. Но они не могут иметь ключевое слово yield, потому что они не могут быть генераторами: «Стрелки не могут быть генераторами, и мы не хотим глубоких продолжений».
Тейн

36

В дополнение к обсуждению на esdiscuss.org и примечаниям к заседаниям комитета ES6 TCM Ecma за ноябрь 2013 года, упомянутым выше, стрелки генератора были вновь рассмотрены на двух совещаниях ES7 в сентябре 2016 года [1] [2] . После обсуждения плюсов и минусов различных синтаксисов (в основном =*>и =>*) и отсутствия обоснований и вариантов использования этой функции они пришли к выводу, что:

  • Комитет заинтересован в некотором интересе, но обеспокоен тем, что эта функция не дает возможности добавить новый синтаксис
  • Запланируйте повторное посещение в День 3, чтобы увидеть, сможем ли мы достичь =>*хотя бы стадии 0, как часть предложения асинхронной итерации [Domenic Denicola]

Предложение генераторов стрел было перенесено на стадию 1 с Бренданом Эйчем и Домеником Дениколой в качестве чемпионов. Упомянутая выше асинхронная итерация была завершена и реализована в 2018 году.

В октябре 2019 года появилось официальное репо Сергея Рубанова с подробным обсуждением синтаксиса и других деталей.


8

У меня тоже был такой же вопрос и я пришел сюда. После прочтения постов и комментариев я почувствовал, что использование генератора в функции со стрелкой выглядит расплывчато:

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

Это может быть главной причиной того, что они не реализовали генератор в связи с функцией стрелки.


Но если бы я был одним из них, я мог бы подумать так:

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

Это похоже на то, что у нас есть асинхронная функция:

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

Потому что с нормальной функцией асинхронный существует ключевое слово , поэтому функция стрелки его использует - async () =>скорее всего, покажется async function().

Но нет такого ключевого слова, как gen or, generatorи, увы, функция стрелки его не использует.

Заключить:

Даже если они хотят реализовать генератор в функции стрелки, я думаю, что им нужно пересмотреть синтаксис генератора в ядре js:

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

И это будет большой ошибкой. Таким образом, держать стрелку подальше от генератора довольно круто.


После комментария @Bergi :

Нет. Предполагается, что функции со стрелками должны быть легкими (и не иметь, например, .prototype) и часто однострочными, в то время как генераторы в значительной степени противоположны.

Я скажу, что целью генератора является запуск-остановка-запуск, и поэтому я не думаю, что нам нужно заботиться о прототипе, лексическом этом и т. Д.


2
Можно также рассмотреть экзотические варианты, а также, как () ~> { yield 'a'; yield 'b'; }. Если честно, я просто люблю тильды.
Гершом

@Gershom Вот как языки программирования, такие как Perl, работают совершенно неправильно
Sapphire_Brick,

2

Я знаю, что это очень поздно, но другой возможной причиной может быть синтаксис. возможно (*() => {})работает, а как же (9 ** () => {})? Возвращает ли это 9 к степени функции стрелки, NaNили же функция возврата стрелки 9 раз тоже NaN? Это может быть сделано с помощью некоторого альтернативного синтаксиса, например, =>*как уже упоминалось в другом ответе, но, возможно, было желание сохранить согласованность синтаксиса функции генератора (например, function* () {}и { *genMethod() {} }) при его реализации. Не слишком оправдание, но причина для этого.


1
: +1: для двойных звездочек ... Парень из старой школы JS здесь. Кто сказал, что вы не можете научить старую собаку новым трюкам: joy:
Shanimal

Единственная причина, по которой они этого не делают, заключается в том, что сделать синтаксический анализатор сложно. Это вполне возможно и не требует компромисса в синтаксисе.
Джейсон Маккаррелл

@JasonMcCarrell Если они достаточно заботятся о том, чтобы не делать синтаксический анализатор слишком сложным, то, возможно, Брендан Эйх должен был поместить Scheme в браузер.
Sapphire_Brick


-4

Есть хороший обходной путь с Redx-сага

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

function* gen() {
   yield all([].map(() => {
      return call(....);
   }));
}

4
Откуда мы знаем, что OP использует Redux?
Марос
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.