Выход ES6: что происходит с аргументами первого вызова next()?

Рассмотрим этот фрагмент кода:

function foo(a) {
  console.log("Mul =", a);
  return a * 2;
};

function * process(start) {
  // next() #1
  var result = start;

  console.log("Pre-processing =", result);
  result = yield foo(result);
  // next() #2
  console.log("Process result 1 =", result);
  result = yield foo(result);
  // next() #3
  console.log("Process result 2 =", result);
  result = yield foo(result);
  // next() #4
  console.log("Process result 3 =", result);

  return foo(result);
}

var it = process(1);
console.log("#1");
console.log("Next 1 =", /*#1*/it.next("bar"));
console.log("#2");
console.log("Next 2 =", /*#2*/it.next(3));
console.log("#3");
console.log("Next 3 =", /*#3*/it.next(7));
console.log("#4");
console.log("Next 4 =", /*#4*/it.next(15));

И вывод

#1
Pre-processing = 1
Mul = 1
Next 1 = { value: 2, done: false }
#2
Process result 1 = 3
Mul = 3
Next 2 = { value: 6, done: false }
#3
Process result 2 = 7
Mul = 7
Next 3 = { value: 14, done: false }
#4
Process result 3 = 15
Mul = 15
Next 4 = { value: 30, done: true }

Почему первый вызов it.next() пропускает аргументы (в приведенном выше коде "bar") вообще? Или, другими словами, почему при последующих вызовах поведение отличается? Я ожидал, что вызов функции генератора пропустит аргументы, и что вызов next() фактически инициализирует итератор, делая процесс более последовательным, не так ли?


person Yanick Rochon    schedule 07.01.2014    source источник
comment
Я ожидал, что вызов функции генератора пропустит аргументы Если это так, вы не сможете передать несколько аргументов. next, похоже, принимает во внимание только первый переданный аргумент. По этой причине аргументы итератора будут переданы генератору. В результате нет возможности получить необязательный аргумент первого next. Хотя это все догадки.   -  person Loamhoof    schedule 08.01.2014
comment
Вы попали в точку. Однако, если назначения деструктурирования когда-либо официальны, это может решить эту проблему. Пример: var [a, b] = yield c; получит аргументы от it.next(1, 2);.   -  person Yanick Rochon    schedule 08.01.2014
comment
На самом деле это ничего не меняет, вам не нужна деструктуризация. Деструктуризация будет работать только в том случае, если yield возвращает массив. В этом случае вы также можете сохранить этот массив в одной переменной. Кроме того, моя точка зрения заключалась в том, что для того, чтобы иметь возможность учитывать аргументы первого next, вам нужно какое-то место для их получения (нет предыдущего yield для их возврата), или они должны быть приведены в аргументы генератора. Дело в том, что это было бы нелогично, потому что next обрабатывает только 1 аргумент atm. Но на самом деле это может измениться.   -  person Loamhoof    schedule 08.01.2014
comment
Это может быть ответ, и я бы проголосовал за него.   -  person Yanick Rochon    schedule 08.01.2014
comment
ваш пример неприлично сложен, и вы на самом деле не говорите, используете ли вы ECMAScript-harmony или JS 1.8. Название и теги не совпадают.   -  person Evan Carroll    schedule 22.01.2014
comment
@EvanCarroll, в тегах написано ecmascript-harmony, и я видел много примеров, которые были простыми, но не могли помочь мне понять, как работают генераторы; большинство из них используют Q, а не чистый пример JS.   -  person Yanick Rochon    schedule 22.01.2014
comment
ECMAScript-Harmony — это не Javascript. Javascript имеет свои собственные спецификации и встроенные версии генераторов, которые даже не требуют function *. Javascript является расширенным набором ECMAScript, и когда ECMAScript играет в догонялки, требуется дифференциация.   -  person Evan Carroll    schedule 22.01.2014
comment
@EvanCarroll, извини, я не вижу смысла в этом комментарии. Без обид, серьезно, но мой пример и тег ясно указывают на гармонию ECMAScript, и мой пример использует определение ECMAScript функции-генератора. Зачем вообще ссылаться на спецификации JS 1.8? Что касается вашего вопроса, то он такой же, как у меня :) Но я думаю, что мне бы больше понравился ответ здесь, так как он содержит более подробную информацию по этому вопросу. Мой пример был, возможно, чрезмерно сложным, но тем не менее четко продемонстрировал проблему.   -  person Yanick Rochon    schedule 22.01.2014
comment
Что касается редактирования. Точность могла и не понадобиться. Вопрос относится как к спецификациям JS, так и к спецификациям ECMA.   -  person Yanick Rochon    schedule 22.01.2014


Ответы (1)


В черновике:

После дополнительных исследований ответ находится в черновике гармонии (см. вики: http://wiki.ecmascript.org/doku.php?id=harmony:generators#methodnext).

Предполагается, что next не имеет аргумента. Однако кажется, что вызов next с одним аргументом эквивалентен вызову send с одним аргументом. Вот ответ. send предназначен для выдачи ошибки, если он вызывается первым (без next до).

Таким образом, вы не должны иметь возможность «инициализировать» свой итератор, передав аргумент next, потому что у вас нет на это полномочий.

В реализациях:

Однако это только спецификация. Подводя итог тому, что было сказано в комментариях, есть как минимум 2 причины, по которым вы не можете передать аргумент своему первому next и должны передать его своему генератору.

Во-первых, вам понадобится какой-то метод, чтобы получить этот аргумент. Вы не можете сделать это так же, как со своими следующими вызовами let myVar = yield myValue.
Второй вариант заключается в том, что next принимает только один аргумент, и это весьма ограничено, в то время как вы можете передать бесконечное количество аргументов своему генератору. при создании итератора.

Однако это только то, что происходит в данный момент. Ничто не говорит о том, что черновик или реализации не изменятся. Мы могли бы, конечно, представить, что send принимает любое количество аргументов (без причин, но эй, кто знает) и может преобразовать их в аргументы генератора. Или что угодно.

person Loamhoof    schedule 08.01.2014
comment
it seems calling next with one argument is just equivalent to call send with one argument -- Есть ли ссылка на это заявление? В черновике не нашел. Благодарю вас! - person zhiyelee; 22.07.2014
comment
Я понял. Метод send удален и заменен аргументом метода next bugs.ecmascript.org/ show_bug.cgi?id=1555 - person zhiyelee; 22.07.2014
comment
@zhiyelee прошло некоторое время, и с тех пор все изменилось, но я думаю, что это мое утверждение было основано на реализациях генераторов того времени (chrome, ff) и, возможно, на чем-то, что было написано на одной из страниц Mozilla, может больше ничего не скажу (и, думаю, это уже не имеет большого значения :)). - person Loamhoof; 22.07.2014
comment
Спасибо за ответ. - person zhiyelee; 23.07.2014