3

In node (0.11.9, with the --harmony flag), how do I restart a generator after it finishes?

I tried doing generator.send(true); but it says the send() method doesn't exists.

Alix Axel
  • 141,486
  • 84
  • 375
  • 483

2 Answers2

5

You don't restart a generator. Once it has completed, it has finished its run like any other function. You need to recreate the generator to run again.

var count = function*(){ yield 1; return 2;};

var gen = count();
var one = gen.next();
var two = gen.next();

// To run it again, you must create another generator:
var gen2 = count();

The other option would be to design your generator such that it never finishes, so you can continue calling it forever. Without seeing the code you are talking about, it is hard to make suggestions though.

loganfsmyth
  • 135,356
  • 25
  • 296
  • 231
  • The code in question is somewhat complex, but I can link you to it if it helps. I was under the impression that generators could be restarted according to [this MDN page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Advanced_generators). – Alix Axel Jan 02 '14 at 19:37
  • That example restarts the *sequence*, not the *generator*. That generator never completes because it is an infinite loop. If that's not enough to get you going the right direction, please post your code. What is assigned to the `generator` that you are calling `send` on? – loganfsmyth Jan 02 '14 at 20:44
  • Yeah, I used the wrong jargon.. Is there a way to restart the sequence though? I'm working on [this](http://stackoverflow.com/a/20875692/89771), specifically near `ret.types.REFERENCE` and `token.remember`. Basically I'm trying to return the previously generated generator when a regex back-reference is iterated, it *kinda works* for the first time but when it sees `\1 \1` the generator is unable to yield more results. Confusing, I know... I think that I could make it work if I could restart the generator sequence, hence this question. – Alix Axel Jan 02 '14 at 23:36
3

A bit late, but this is just a FYI.

At the moment, the send method is not implemented in Node, but is in Nightly (FF) - and only in some way.

Nightly:

If you declare your generator without the *, you'll get an iterator that has a send method:

var g = function() {
  var val = yield 1; // this is the way to get what you pass with send
  yield val;
}
var it = g();
it.next(); // returns 1, note that it returns the value, not an object
it.send(2); // returns 2

Node & Nightly:

Now, with the real syntax for generators - function*(){} - the iterators you produce won't have a send method. BUT the behavior was actually implemented in the next method. Also, note that it was never intended for send(true); to automatically restart your iterator. You have to test the value returned by yield to manually restart it (see the example in the page you linked). Any value, as long as it's not a falsy one, could work. See for yourself:

var g = function*() {
  var val = 1;
  while(val = yield val);
}
var it = g();
it.next(); // {done: false, value: 1}
it.next(true); // {done: false, value: true}
it.next(2); // {done: false, value: 2}
it.next(0); // {done: true, value: undefined}
Loamhoof
  • 8,163
  • 24
  • 29