4 ms·
The fact that you must call send() on a coroutine to start it is very confusing -- what distinguishes function from a coroutine? The presence of 'yield' inside
by a1k0n 14y ago
The fact that you must call send() on a coroutine to start it is very confusing -- what distinguishes function from a coroutine? The presence of 'yield' inside a function body magically means calling that function doesn't actually return the return value of the function, but a new coroutine which hasn't executed any of its body? This is even more confusing than the function-as-an-object syntax, where at least the new keyword distinguishes the behavior.
I am very much in favor of coroutines in javascript, but I'm kind of surprised by this choice of implementation.
- ionforce 14y agoI came to post this exact question. I am also curious how coroutines typically work and if this is the expected pattern.
- kilovoltaire 14y agoThe Javascript 1.7 coroutine/generator syntax is copied verbatim from Python. I agree this seems like a weird choice, since Javascript is much more function-oriented than Python. As for needing to send() first to get it started, this kind of makes sense given that the same syntax is used for generators as well, so there is kind of an off-by-one difference between generators (which return a value from the first send()) and coroutines (which tend not to return values).
- pfraze 14y agoI'm not sure what's with OP, but according to [1] (and the example on tasks.js) a generator-producing function should have an asterisk before the name. function *myCoroutine() { ... } 1. http://www.2ality.com/2012/07/esnext-classes.html http://www.2ality.com/2012/07/esnext-classes.html
- kilovoltaire 14y agoCool, I didn't know about that syntax! Unfortunately it isn't yet supported in Firefox, but I'm glad something like that is in the works.
- pfraze 14y agoHope I didn't offend. I really enjoyed your post; the coroutine syntax seems like an extraordinarily intuitive approach to state machines. Game-changing, maybe. Look forward to trying it.
- a1k0n 14y agoSo, in lieu of the new function* syntax, the presence of the yield keyword in the body is the only thing that distinguishes a generator from a regular function, in the current Firefox implementation?
- thejsjunky 14y agoWhat you have to realize is what we are dealing with here are Generators; a generalized way to create custom Iterators. This article is focusing solely on using Generators for a coroutine system and doesn't elaborate on much so it might seem a bit confusing. Here's a basic run-down: You create a Generator Function: function NumsUpTo100(start) { do { yield start; start += 1; } while (start < 100); } The thing that differentiates this from a regular Function (note: the proposed function* syntax would distinguish it visually as well) is that it actually constructs a new Generator: var myGen = NumsUpTo100(20); myGen now holds a Generator object. You use the arguments to initialize the state of the Generator. Generators are Iterators, so they really shine in that respect: for (var n in NumsUpTo100(50)){ console.log(n); } However, sometimes you want to manually step through iteration yourself, and you can do that by repeatedly calling .next() on your generator. It will either go forever or eventually throw StopIteration depending on how you wrote it. AFAIK this article is actually incorrect as you have to call .next() to start the Generator before you can call .send(). Calling send() with no arguments is functionally the same as calling .next(), but last I heard it would throw an error. The utility of .send() is sometimes during iteration you might want to send information to the generator. For example, maybe you have some sort of state machine in your generator and you want to be able to explicitly reset it's state. Generators are very useful in general, coroutines is just one fun thing you can do with them.
- cynwoody 14y ago>Calling send() with no arguments is functionally the same as calling .next(), but last I heard it would throw an error. I just tried one in Firefox 17, and you can prime it by calling send() with no argument. It objects if there is an argument on the initial send().
- deleted 14y ago[deleted]
- kilovoltaire 14y agoYeah this is a nice advantage of Javascript over Python: send() is equivalent to send(undefined) which is equivalent to next(). This equivalence is true in Python as well, but you have to explicitly call send(None) which is annoying.
- tlrobinson 14y agoI agree. I assumed that was an error at first, but he kept doing it.