On Sep 5, 2011, at 9:36 PM, John J Barton wrote:

> On Sun, Sep 4, 2011 at 1:42 PM, Brendan Eich <[email protected]> wrote:
> On Sep 4, 2011, at 11:06 AM, John J Barton wrote:
> 
>> As a reader I have to parse the function carefully to look for the 'yield'. 
>> If I find one, then I know that this is not actually a function after all. 
>> Then I need to mentally draw a line after the yield and label it 
>> "entry-point #2".
> 
> This is addressed in ES6 by changing the head of the generator function as 
> follows:
> 
> spawn(function* () {
>     try {
>         var [foo, bar] = yield join(read("foo.json"),
>                                     read("bar.json")).timeout(1000);
>         render(foo);
>         render(bar);
>     } catch (e) {
>         console.log("read failed: " + e);
>     }
> });
>  (For others who have some trouble seeing the difference, here the function 
> keyword is followed by the multiplication symbol).
> 
> "generator() {}" would make a lot more since to me, it would more clearly 
> alert the reader at no added cost for the writer, as well as helping new 
> users of this feature separate it's effect from functions.

We considered that, but generator is not reserved, and reserving it in ES6 
requires newline sensitivity at least. Consider an anonymous generator similar 
to the one you typed:

  generator()
  {...}

where ... is actual code (and the {...} style may use multiple lines and 
indentation). This could be valid code in the field today, relyling on ASI to 
insert the semicolon after "generator()".

What's more, the precedent in Python is not a negative or a trivial benefit. 
Besides reusing brain-print, we stand on field-tested design in a similar 
language. Python uses def for both functions and generators.


>> Next I have to read through the source of spawn() and track the lifetime-of 
>> and references-to the object it received, seeking calls to send().
> 
> No, you can use spawn as a black box. It's an API entry point to the taskjs 
> library. You do not need to read the source to use an API.
>  
> Hmm., the doc http://dherman.github.com/taskjs/doc/api.html says:
>   Task spawn(generator function thunk)
> But as I understand it, the send() plays a role in the API to spawn correct?

The value sent to yield expressions in your generator, yes. So? Again that does 
not mean you must read the inside of the black box. The API docs may be 
lacking, of course :-|.


> 
> 
> 
>> Assuming I am understanding the idea, then my description above is also my 
>> criticism: control and data flow is jumping around in unusual ways and 
>> functions morph into multi-entry point things with new API.
> 
> There's no free lunch. Either we renounce adding new syntax by which to 
> capture a shallow continuation, which leaves us with the nested callback 
> function world of today, which people object to on several grounds:
> 
> * Nesting makes hard-to-read, rightward-drifting function spaghetti.
> 
> * Nesting increases the risk of capturing too much environment, potentially 
> entraining memory for a long time -- bloat and leak bugs.
> 
> These are not unmanageable according to some JS hackers, but they are not 
> trivial problems either. They keep coming up, in the Node community and among 
> browser JS developers. They're real.
> 
> So it is known that no alternative exists beyond these two choices?

On this list, we have been over the design space many times. Please search for 
call/cc and "shallow continuations" using site:mail.mozilla.org. I'm short on 
time now.

The upshot is that you're suggesting threads, or deep continuations. Threads 
suck, we are not exposing JS developers to preemptively scheduled threads in a 
language with shared-object mutation and therefore significant data races.

Deep continuations have two problems:

1. They break the ability to reason about loss of invariants due to an event 
loop turn being taken under what looks like a function call.

2. The second problem is that different implementations will not agree on 
capturing deep continuations across native frames, but interoperation demands 
one standards. Forbidding capture across native frames breaks abstraction over 
self-hosted vs. native code (e.g. Array map calling its downward funarg). 
Requiring will mean that some VMs won't be able to conform to such a spec -- 
Java, .NET, any without hand-coded magic to deal with compiler magic involving 
native frame representation.

This leaves shallow continuations, and generators won out in a fair fight with 
a more minimal "shift" proposal for shallow continuations (too minimal).

Generators share with private name objects a right-sized (minimal but not too 
small) gap-filling quality that supports all of:

* prompt standardization,
* interoperable implementation, and
* library ecosystem builder upside far beyond what TC39 could ever do on any 
schedule.

They're in ES6 for good reason.

/be
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to