yield syntax

David-Sarah Hopwood david-sarah at jacaranda.org
Sun May 17 16:56:19 PDT 2009

Brendan Eich wrote:
> This may be breaking a butterfly on a wheel, but I am game if it
> improves the state of the strawman proposals.
> On May 15, 2009, at 7:16 PM, David-Sarah Hopwood wrote:
>> My point was that the example of 'yield (foo)' (that is, yield as a
>> prefix operator applied to the expression '(foo)') shows that the prefix
>> operator syntax cannot possibly be easier to specify than the function
>> call syntax -- contrary to what you appeared to be arguing above.
> Analogous to direct vs. indirect eval in ES5 (, there is no
> purely syntactic specification for what Neil proposes. A runtime check
> is required. So I don't see why you are focusing only on syntax here.

Maybe I misunderstood what Neil was proposing, but I took him to mean
something equivalent to:

 - parse using essentially the current grammar.
 - if the text of the CallExpression in 'CallExpression Arguments',
   or of the MemberExpression in 'MemberExpression Arguments',
   is "yield" (excluding comments and whitespace), then the call
   is a yield-expression.

This is a purely syntactic specification.

It does have some quirks: if you define a function called 'yield' and
try to call it, then the call will still be treated as a yield-expression
rather than a function call. For that reason I'm going cold on the idea.
I would prefer something entirely unambiguous, like

  @yield expr

or an opt-in that makes 'yield' (and 'let') reserved everywhere.
Either would make parentheses around a yield expression unnecessary,
or at least not necessary in as many cases. ('yield' would behave
syntactically like 'typeof', perhaps with lower precedence.)

>> Show me an unambiguous grammar for the prefix yield operator, and
>> then I'll concede the point :-)
> Python 2.5 has essentially the same issues,

Python does not attempt to contextually reserve 'yield'.
It uses an opt-in that makes 'yield' a keyword that is reserved
everywhere. From PEP 255:

#  A new statement is introduced:
#      yield_stmt:    "yield" expression_list
#  "yield" is a new keyword, so a future statement[8] is needed to phase
#  this in:  in the initial release, a module desiring to use generators
#  must include the line
#      from __future__ import generators
#  near the top (see PEP 236[8]) for details).  Modules using the
#  identifier "yield" without a future statement will trigger warnings.
#  In the following release, yield will be a language keyword and the
#  future statement will no longer be needed.

> and it has a formal grammar
> (several, the one CPython uses and at least one other at antlr.org).
> From CPython's Grammar/Grammar EBNF:
> $ grep yield Grammar
> expr_stmt: testlist (augassign (yield_expr|testlist) |
>                      ('=' (yield_expr|testlist))*)
> flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt |
> yield_stmt
> yield_stmt: yield_expr
> atom: ('(' [yield_expr|testlist_gexp] ')' |
> yield_expr: 'yield' [testlist]

That would be ambiguous, if (hypothetically) 'yield' were not a
keyword in Python. For example

  (yield (foo))

would match both a parenthesised <yield_expr>, and a parenthesised
<NAME> 'yield' followed by a trailer giving function arguments.
(This involves the <power>, <trailer>, <arglist> and <argument>
productions that weren't found by your grep.)

Similarly for (yield - 1) or (yield + 1) or (yield /re/g) in Harmony.
If these are treated as being yield-expressions, then that is
not compatible with any ES3/5 code using 'yield' as a variable
name, but if they are treated as having their ES5 meaning, then
there are a bunch of ugly special cases for what token can
validly begin the expression after 'yield'.

> What we are discussing is almost trivial in terms of usability, but the
> difference is big enough to care about, IMHO.

Unambiguous grammar first, please.

David-Sarah Hopwood ⚥

More information about the es-discuss mailing list