Hi, I'm back. Not sure I totally figured it out, but I thought it was probably 
time to "yield" my reasoning before iterating further ;-)


To achieve a different result, I figured out we probably needed to start from a 
different sets of initial assumptions. So here are my new set of assumptions: 

    - We don't need to support the yield operator in non-strict code. If 
someone is in the process of defining a new function, it can simply trigger the 
strict mode in this new iterator function if he wants to yield inside it. 
However, that shouldn't be needed in the future as ES strict is the new default 
in modules, and we can expect that almost all iterators will be defined inside 
the strict regions thereby defined. This also guarantees that "yield" is not 
used in a context where strange things may happen, and comes together with a 
whole set of new features.

    - We don't want to introduce magic stuff where it isn't needed, but we want 
to keep most of the power of syntaxic sugar. Iterators are kinda achievable in 
pure ES5, only complex to write (state machine) and sometimes even more to 
read. However we should probably allow someone that want to implement is own 
"yield" logic to do so if he wants to, and not restrict the Iterator usage to 
the sole built-in "yield syntax" (this follows the Extensible Web principles).

    - We want to keep the idea that the reader should quickly understand when 
reading a function that it create an iterator. However, since creating state 
machines can be useful for multiple purposes, we could probably allow creating 
a state machine function without all the magic related to iterators.

    - Since introducing keywords is hard, we should focus on providing a good 
pattern library (at runtime) instead of syntax-related tricks (at compile-time)



When working under this set of assumptions, I came with the following idea:

function getNumberIteration(filter) {
        return new Iterator(=> {
                
                var i = 0; while(1) {
                        if(filter(i)) yield i;
                        i++;
                }
                
        });
}

==

function getNumberIteration(filter) {
        return new Iterator(=> {
                
                var i = 0; return @NEXT(); 
                
                function @NEXT(injectedValue) {
                        while(1) {
                                if(filter(i)) { 
                                        
                                        return { 
                                                value: i, 
                                                next: @NEXT
                                        };
                                        
                                }
                                i++;
                        }
                }
                
        });
}

Basically, using yield into a function create a state machine for the function 
and does run the function normally until the first encountered state switch 
(first yield statement here). In some sense, the function is almost normal, we 
could barely consider this kind of "yield" like a new kind of "return" that 
also return a pointer to a function that allows to continue the execution. You 
can totally write that in plain JS which will allow TypeScript-like compilers 
to generate for you the ES5-compatible code for your ES6 iterator, and use it 
on ES5-compatible browsers the exact same way you do on an ES6-browser.

It also allow you to use lambda functions, which is quite a great nice-to-have.




So, let's see how I address the 3 reasons behind function* :

> Three reasons for function* syntax:
> 
> 1. Opt-in required for backward-incompatible definition of 'yield' as 
> low-precedence unary prefix operator.

Works as-is in modules, requires defining "use strict" in the function body if 
you want to use outside the strict context.


> 2. Zero-yield (no yield in body) basis case, useful for delegation via
> yield* from another generator.

Removed. The zero-yield logic is encapsulated into the Iterator class, which 
only call the iterator function when required.


> 3. Decorator to alert the reader that the body contains yield (ignoring
> 2 for a moment) reason.

Provided by the fact you have to create an instance of Iterator, which 
instantiation should be pretty easy to spot.



This is certainly another set of tradeoffs, but I tend to like it more (even if 
it may still require tweaks or may just don't fit for some reason I didn't 
think about) than the current one.

What's your opinon?
Francois
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to