Nathan-Wall / proto

A programming language derived from JavaScript which emphasizes prototypes, integrity, and syntax.
Other
12 stars 1 forks source link

Generator's first next argument #93

Open Nathan-Wall opened 10 years ago

Nathan-Wall commented 10 years ago

Problem

This is one of the most difficult syntax and/or control flow design problems.

In currently drafted ES6, the first call to next() cannot be passed an argument because the generator doesn't have a place to put it. (Python generators are similar.) That makes doing certain kinds of generators awkward. For instance, take this echo generator:

gen fn echo :{
    var x;
    while true: x = yield x;
}

var iter = echo();
iter.next(); // Just need to get things started.
console.log(iter.next(3)); // 3
console.log(iter.next(7)); // 7
console.log(iter.next(2)); // 2

The first call to next is just a throwaway because the echo generator isn't able to do anything with a value passed in[1]. At the very least this is awkward. Worse, it means generators can exist in one of two different state: (a) next has not been called, and (b) next has been called. Having both kinds floating around limits the certainty that you can just use any generator in a generic function and have things work.

Priming Generators

The best solution I can come up is to use some kind of syntax to specify that a particular generator can be "primed" (or run up to the first yield when instantiated). The echo generator could be written as follows:

prime gen fn echo :{
    var x = yield;
    while true: x = yield x;
}

var iter = echo();
console.log(iter.next(3)); // 3
console.log(iter.next(7)); // 7
console.log(iter.next(2)); // 2

Generators declared with the prime modifier would begin execution not with the first next but when an iterator is generated. When echo() is called, the generator's code goes ahead and executes up to the first yield. Then the first next will be able to pass a value to this yield.

Restrictions

Under this system it would be illegal to yield a value for the first yield of a prime generator, resulting in either a compilation error or a runtime error (I'm not sure which). Likewise, passing a value to the first next call for a standard (non-prime) generator would be illegal (like in ES6 and Python) and result in a runtime error. I think there's a nice symmetry to this system.

[1] https://mail.mozilla.org/pipermail/es-discuss/2014-August/038872.html