'function *' is not mandatory

Brendan Eich brendan at mozilla.com
Sat Aug 31 20:58:16 PDT 2013


> Till Schneidereit <mailto:till at tillschneidereit.net>
> August 31, 2013 6:05 PM
> On Sun, Sep 1, 2013 at 2:43 AM, Brendan Eich <brendan at mozilla.com 
> <mailto:brendan at mozilla.com>> wrote:
>
>     Lots of constructors/factories out there. An essential (see
>     Aristotle) argument for why function* for generator syntax
>     (ignoring trumping reasons 1&2) must say why *this* particular
>     factory needs special (a la function*) head syntax.
>
>
> For all non-generator functions, one important assumption for reading 
> them holds: they always start with the first instruction, and any 
> (potential) deviations from linear control flow are visible exactly 
> where they (might) happen. Not so for generators:

True so far, and I said so later in the same message:

"""
>    A regular Function's body is evaluated before its call returns.

Yes, generators have an implicit yield; at the top. Now you have hit an 
essential difference with other functions.

"""

but then (in a glass house myself, not throwing stones), you move away 
from pointing out the leading implicit yield, to talking about later 
explicit yields. Those are different for generators too, assuming there 
are any -- but since a generator can be explicit yield free, yet still 
has that implicit yield at the front.

So I think the later yields are not sufficient, even though present in 
by far the common cases, to argue for an essential difference. It's the 
leading implicit yield that makes generator functions different enough 
from regular functions to merit function* syntax.

/be

> to understand what invoking a generator might do, you have to look at 
> all the potential entry points, i.e., all instructions following a 
> yield in the control flow. If you want to do more localized reasoning 
> and are interested in a specific invocation, you also have to reason 
> about which might be the relevant one. Granted, that is essentially 
> state and any function's control flow can be state-dependent, so this 
> point might be less important.
>
> Still, having to look at an unknown number of entry points to 
> understand how control flows through a piece of code seems like 
> something you'll want to know about. Without searching the code for 
> "yield".
> Brendan Eich <mailto:brendan at mozilla.com>
> August 31, 2013 5:43 PM
> Allen Wirfs-Brock wrote:
>> On Aug 31, 2013, at 3:19 PM, Brendan Eich wrote:
>>
>>> >  Brian Kardell wrote:
>>>> >> >>  Fwiw, just bikesheddingly speaking I actually prefer the *.
>>>> >> 
>>> > >  Let's review. Three reasons for function* syntax:
>>> > >  1. Opt-in required for backward-incompatible definition of 
>>> 'yield' as low-precedence unary prefix operator.
>>> > >  2. Zero-yield (no yield in body) basis case, useful for 
>>> delegation via yield* from another generator.
>>> > >  3. Decorator to alert the reader that the body contains yield 
>>> (ignoring 2 for a moment) reason.
>>> > >  You are "bikesheddingly" supporting 3, I take it. Can you say 
>>> more about why you want a decorator for human readers? Again 
>>> ignoring 2, which makes the case based on what the JS engine must 
>>> see, a more "objective" criterion in this case (and, in a different 
>>> light, in case 1).
>>
>> I think there is more to #3. The body of a GeneratorFunction has 
>> quite different semantics than that of a regular function.
>
> Not necessarily. See Yuichi's reply to Mark.
>
>>   This is particularly clear when you think about GFs as actually 
>> being constructors/factories.
>
> Lots of constructors/factories out there. An essential (see Aristotle) 
> argument for why function* for generator syntax (ignoring trumping 
> reasons 1&2) must say why *this* particular factory needs special (a 
> la function*) head syntax.
>
>>    The body of a normal constructor/factory defines what happens 
>> before a new instance object is returned to a caller.  The body of a 
>> GeneratorFunction defines the future  behavior of the instance object 
>> that is returned to the caller.
>
> Functions may diverge (iloop/recurse-to-death). They may contain dead 
> code. Yuichi's right, there has to be more to Mark's partial program 
> understanding than just whether top-level (balanced) code runs at all, 
> if one is making an essential distinction between generator functions 
> and other functions.
>
>>    A regular Function's body is evaluated before its call returns.
>
> Yes, generators have an implicit yield; at the top. Now you have hit 
> an essential difference with other functions.
>
>>    A GeneratorFunction's body is evaluated sometime after its call 
>> returns.
>
> This is ill-stated. You mean a continuation of a yield in its body is 
> evaluated, not the whole body (re-)evaluated.
>
> Of course, there may be no yield, or the yield may not be reached. 
> Yuichi pointed out similarity with return.
>
>>    This is a critical difference that must to known to a code reader 
>> in order to understand any code that includes a GeneratorFunction 
>> definition and is more that sufficient to warrant the * sigil.
>
> TC39ers agree but it's good we have reasons 1&2, because consensus on 
> 3 alone is fragile. Especially with lousy arguing and rehashing 
> resolved points (next).
>
>>     Personally, I would prefer an even stronger marker, such as a 
>> different keyword,
>
> Please don't rehash. A different keyword breaks use-cases including 
> function expressions (remember, we can't use a restricted production 
> based on [no LineTerminator here] for 'generator' if it can start an 
> arbitrary primary expression).
>
>>   but * is adequate.
>
> It's more than adequate, but I won't rehash. :-|
>
>>    Programming language need to be designed for people.
>
> This begs the question of how Python, Ruby, Lua get by without a head 
> sigil. Don't "people" use those languages too? C'mon!
>
>>   Inferring which functions are GeneratorFunction by the presences of 
>> yield
>
> This forgets the zero-yield basis case, but nm.
>
>>   may be fine for compilers but it isn't good enough for human 
>> readers or writiers.
>
> Python, etc., have human readers and writers.
>
> I'm taking Yuichi's side here not just be argumentative. We need 
> better discourse and stronger consensus. Up your game! :-P
>
> /be
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
> Allen Wirfs-Brock <mailto:allen at wirfs-brock.com>
> August 31, 2013 4:51 PM
>
> I think there is more to #3. The body of a GeneratorFunction has quite 
> different semantics than that of a regular function. This is 
> particularly clear when you think about GFs as actually being 
> constructors/factories. The body of a normal constructor/factory 
> defines what happens before a new instance object is returned to a 
> caller. The body of a GeneratorFunction defines the future behavior of 
> the instance object that is returned to the caller. A regular 
> Function's body is evaluated before it's call returns. A 
> GeneratorFunction's body is evaluated sometime after its call returns. 
> This is a critical difference that must to known to a code reader in 
> order to understand any code that includes a GeneratorFunction 
> definition and is more that sufficient to warrant the * sigil. 
> Personally, I would prefer an even stronger marker, such as a 
> different keyword, but * is adequate. Programming language need to be 
> designed for people. Inferring which functions are GeneratorFunction 
> by the presences of yield may be fine for compilers but it isn't good 
> enough for human readers or writiers.
>
> Allen
> Brendan Eich <mailto:brendan at mozilla.com>
> August 31, 2013 3:19 PM
>
>
> Let's review. Three reasons for function* syntax:
>
> 1. Opt-in required for backward-incompatible definition of 'yield' as 
> low-precedence unary prefix operator.
>
> 2. Zero-yield (no yield in body) basis case, useful for delegation via 
> yield* from another generator.
>
> 3. Decorator to alert the reader that the body contains yield 
> (ignoring 2 for a moment) reason.
>
> You are "bikesheddingly" supporting 3, I take it. Can you say more 
> about why you want a decorator for human readers? Again ignoring 2, 
> which makes the case based on what the JS engine must see, a more 
> "objective" criterion in this case (and, in a different light, in case 
> 1).
>
> /be
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
> Brian Kardell <mailto:bkardell at gmail.com>
> August 31, 2013 3:11 PM
>
> Fwiw, just bikesheddingly speaking I actually prefer the *.
>


More information about the es-discuss mailing list