Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-20 Thread kevin curtis
Brendan:
 I'm abusing Object as ES5 does, but harder, to avoid polluting the global
 object. I'm supposing Object.implementation could be useful for other
 properties than the supports method. This reads well enough, although its a
 bit long-winded altogether (but individual names are short enough).
 Comments?

Have i got the wrong end of the stick on this...
With ES6 i thought modules would provide some namespace functionality. eg

import meta // or whatever the syntax is
meta.supports(yield)

And a home for any ast functionality:
import ast
let x = ast.parse(3 + 3)

It's interesting that Lua puts its yield/coroutine functionality in a module:
coroutine.yield()

It's function format but at least it's not necessary to worry about
the global namespace (with modules).



On Mon, May 18, 2009 at 8:13 PM, Brendan Eich bren...@mozilla.com wrote:
 On May 18, 2009, at 11:53 AM, Neil Mix wrote:

 But for this to be true, we would need to use the direct-eval detection
 hack I mentioned previously.

 On the plus side, this would allow for feature detection of generator
 support, right?  (Is there any other way to detect generator support?)

 In JS1.7 you could object-detect:

    if (this.Iterator) ...

 or similarly.

 But I'm in the midst of writing up strawman:iterators proposal that doesn't
 add Iterator to the global object (nor any __iterator__ getter, no double
 underscores).

 One generalized idea for object detection of keywords that could be used as
 if they named functions in code that would be work in old browsers:

    if (Object.implementation  Object.implementation.supports('yield'))) {
        ...
        function gen() { ... yield(E);  }
        ...
    } else {
        ... do something else ...
    }

 I'm abusing Object as ES5 does, but harder, to avoid polluting the global
 object. I'm supposing Object.implementation could be useful for other
 properties than the supports method. This reads well enough, although its a
 bit long-winded altogether (but individual names are short enough).
 Comments?

 /be
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax

2009-05-19 Thread David-Sarah Hopwood
Igor Bukanov wrote:
 2009/5/18 Brendan Eich bren...@mozilla.com:
 On May 18, 2009, at 2:25 AM, Igor Bukanov wrote:
 The plus side of this is that an empty generator can be created with a
 straightforward:

  Generator(function() {})

 and not with a rather unnatural

  (function() { if (false) yield; })()
 No one makes empty generators.
 
 For me the problem with the way the generators are defined is that a
 dead code like that if (0) yield; affects the semantic by mere
 presence of it. Surely, this is not the first feature in ES that has
 that property - if (0) var a; is another example. But if (0)
 yield; sets a new record affecting the nature of the whole function.

A more explicit alternative is to require some kind of decoration on the
function definition, e.g. (just a straw man):

  function generator foo() { ... }

-- 
David-Sarah Hopwood ⚥

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax

2009-05-19 Thread Brendan Eich

On May 19, 2009, at 2:00 PM, David-Sarah Hopwood wrote:

*If* it is allowed, then it should be two. It would be very  
surprising if


 foo(a = b, c);

had two arguments (as it does), but the above expression with yield
had one.

But I agree that it may be better not to allow it.


Good; it was a loophole in JS1.7 and up, which I think should be closed.



Agreed; this closes the assignment expression loophole.


This would disallow

 foo(yield x);

which seems unnecessary.


I thought so too, but Python keeps its grammar simple this way, and  
simpler is better, ceteris paribus. JS1.7 allows this but also suffers  
the assignment loophole. Getting rid of the latter but not the former  
is grammar-hacking busy work. I haven't done it in the WebKit/ 
JavaScriptCore/parser/Grammar.y.


/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax

2009-05-19 Thread Brendan Eich

On May 19, 2009, at 2:08 PM, David-Sarah Hopwood wrote:

A more explicit alternative is to require some kind of decoration on  
the

function definition, e.g. (just a straw man):

 function generator foo() { ... }


Or just (we discussed this briefly last summer in Oslo):

generator foo() { ... }

In JS1.7, we followed Python, which uses def, same as for defining a  
function, and distinguishes generators by presence of yield (which  
makes value returns illegal). It seems unwise to diverge from Python  
without more evidence of an actual usability problem. We have no such  
evidence from shipping JS1.7 and up in Firefox 2 and up.


/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-18 Thread Brendan Eich


On May 18, 2009, at 2:25 AM, Igor Bukanov wrote:


The remedy for this is simple - the generator can be created using
explicit call like Generator(f, arg1, ... argN). This would turn any
function into a generator and would allow for runtime checks for eval.


You mean yield, not eval, right?



The plus side of this is that an empty generator can be created with a
straightforward:

  Generator(function() {})

and not with a rather unnatural

 (function() { if (false) yield; })()


No one makes empty generators.

I think this cure is worse than the disease! The problem of yield's  
precedence can be solved by mandating parenthesization as Python does  
-- or if ugliness prevails, as Neil proposes :-P. It doesn't need more  
runtime magic machinery and global constructors that are otherwise  
unmotivated.


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-18 Thread Neil Mix
Nothing prevents you from writing yield(E) of course -- but you're  
arguing that foo(a = yield(b), c) should be enough, no extra parens  
required -- no foo(a = (yield(b)), c). Right?


Yes that's correct.


Pros for yield(E):
- backward compatible


But for this to be true, we would need to use the direct-eval  
detection hack I mentioned previously.


On the plus side, this would allow for feature detection of generator  
support, right?  (Is there any other way to detect generator support?)



- easier to read (to my eye)
- it feels more correct to me in context of the when-using-send- 
value rule


These are subjective enough there's no point in arguing. I hear ya.


Yes, one man's opinion and experience.  If others chimed in claiming  
the opposite experience, obviously my argument would be moot.  But I  
hope I'm providing a decent average hacker POV for you.



Pros for (yield E):
- consistent with python
- doesn't present any is-it-a-function? ambiguities


These are more objective (no look  feel ;-). There is a borrowing  
from Python. There isn't a function call going on.


Agreed.  If look-and-feel weren't factors, I wouldn't have brought it  
up.  ;)


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-18 Thread Igor Bukanov
2009/5/18 Brendan Eich bren...@mozilla.com:

 On May 18, 2009, at 2:25 AM, Igor Bukanov wrote:

 The remedy for this is simple - the generator can be created using
 explicit call like Generator(f, arg1, ... argN). This would turn any
 function into a generator and would allow for runtime checks for eval.

 You mean yield, not eval, right?

Right, that was a typo.


 The plus side of this is that an empty generator can be created with a
 straightforward:

  Generator(function() {})

 and not with a rather unnatural

  (function() { if (false) yield; })()

 No one makes empty generators.

For me the problem with the way the generators are defined is that a
dead code like that if (0) yield; affects the semantic by mere
presence of it. Surely, this is not the first feature in ES that has
that property - if (0) var a; is another example. But if (0)
yield; sets a new record affecting the nature of the whole function.

 It doesn't need more runtime
 magic machinery and global constructors that are otherwise unmotivated.

That is true, but then runtime-only generators allows to avoid opt-in
tax for all the users. How high is that tax I do not know, but surely
it prevents some user cases for the feature.

Igor
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-18 Thread Brendan Eich

On May 18, 2009, at 11:53 AM, Neil Mix wrote:

But for this to be true, we would need to use the direct-eval  
detection hack I mentioned previously.


On the plus side, this would allow for feature detection of  
generator support, right?  (Is there any other way to detect  
generator support?)


In JS1.7 you could object-detect:

if (this.Iterator) ...

or similarly.

But I'm in the midst of writing up strawman:iterators proposal that  
doesn't add Iterator to the global object (nor any __iterator__  
getter, no double underscores).


One generalized idea for object detection of keywords that could be  
used as if they named functions in code that would be work in old  
browsers:


if (Object.implementation   
Object.implementation.supports('yield'))) {

...
function gen() { ... yield(E);  }
...
} else {
... do something else ...
}

I'm abusing Object as ES5 does, but harder, to avoid polluting the  
global object. I'm supposing Object.implementation could be useful for  
other properties than the supports method. This reads well enough,  
although its a bit long-winded altogether (but individual names are  
short enough). Comments?


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-18 Thread Neil Mix


On May 18, 2009, at 12:23 PM, Brendan Eich wrote:

Making them mandatory is the issue. You can derive whatever comfort  
you want from 'em, but they are not required and we're not going to  
start requiring them for return, delete, or typeof. So mandating  
parentheses for yield is kind of wrong. Obviously the issue would go  
away if the precedence where the same as delete and typeof. Hence  
kind of.


Ah, but delete and typeof are different in that they both *require* an  
argument (terminology be damned, hopefully you understand what I mean  
by that.) And return is different because it can't be used in an  
expression.  See my previous let x = yield-5; example -- let x =  
typeof-5; is unambiguous.


I'm tempted to argue that yield should require an argument, and then  
you could give it precedence equivalent to delete and typeof.  But  
that would make a statement like


  yield x - 1;

utterly confusing.

Set aside for a moment the argument of *which* form of parenthesis for  
a moment, and assume (yield E) wins for now.  Could we redefine yield  
so that it has two forms, a statement form and an expression form?   
The statement form would be

  yield E;
where E is optional.  And the expression form would be
  yield E
where E is required, and yield has precedence equivalent to delete and  
typeof.  Is that possible?  Doing so would render any argument about  
parenthesis moot, since they'd rarely be required, right?

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-17 Thread Brendan Eich
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 (15.1.2.1.1), 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.


All the costs count, but considering who pays can trump how much;  
see the postscript below. I'm more concerned with usability than  
implementability, but the latter is not hard and there's no soundness  
issue.




In fact I think it is much harder to do correctly.


See below, it's quite easy.


Yes, but it's not that complicated. SpiderMonkey and Rhino do it.  
Code

size burden is in the noise.


Hmm. SpiderMonkey and Rhino use ad-hoc parsers. 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, 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]

What we are discussing is almost trivial in terms of usability, but  
the difference is big enough to care about, IMHO. Either you have to  
write, in Neil's approach:


yield (E)  (or just yield() to yield undefined)

or in the Pythonic approach:

(yield E)  (or just (yield))

with the parentheses in the Pythonic approach not required when the  
yield expression is either (a) the entire expression in an expression  
statement; (b) the right-hand side of an assignment.


Python differs from JS by having only assignment statements, not  
assignment expressions, which simplifies the problem a bit, as the  
grep output cited above shows.


In any case, yield E; as a statement is the most common kind of yield  
in real-world Python code, both because it came first and because  
sending values to generators is less commonly done than iterating  
generators.


So with either approach you have some insignificant, silly  
parentheses -- but with Neil's approach you have lots more because  
the expression-statement yield must have at least () after the keyord.


This tips the usability contest in favor of the Pythonic approach.

In no case are there ambiguities for a bottom up grammar. The right  
parenthesis avoids nasty automatic semicolon insertion problems that  
plagued the unbracketed low-precedence expression on the right of a  
high-precedence prefix in the case of expression-bodied functions, AKA  
expression closures (see https://mail.mozilla.org/pipermail/es-discuss/2008-October/007888.html) 
.


To confirm this, I patched WebKit's Bison grammar for JS to support  
yield //a la// JS1.7. I didn't hook up the semantic actions, just  
verified zero reduce-reduce conflicts. Patch attached below --  
comments welcome (including from you WebKit lurkers :-).


/be

P.S. Bean-counting productions in a bottom-up grammar is counting the  
wrong cost, given the few implementors and their greater skills,  
compared to the many users who need to be spared those painful and  
fruitless parentheses.


Bean-counting productions in a traditional bottom-up grammar is also  
silly given how many are required for ES1-3. From the patch, notice  
all the existing specialized NoIn/NoBF/NoNode variants in parser/ 
Grammar.y (NoBF = No Brace at Front, as far as I can tell).


Much of that production-forking could be avoided by using either  
parameterized LR parsing (www.cs.lth.se/Research/LDTA2004/d09_TheimannNeubauer.pdf) 
, or else top-down (ad-hoc or not :-P) parsing.





patch
Description: Binary data


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-17 Thread Brendan Eich

On May 17, 2009, at 11:00 AM, Brendan Eich wrote:

Python differs from JS by having only assignment statements, not  
assignment expressions, which simplifies the problem a bit, as the  
grep output cited above shows.


Of course this makes trouble with automatic semicolon insertion,  
unless assignment statements are split from assignment expressions.  
D'oh!


js function g() {z = yield a ? f : x++()}
typein:2: SyntaxError: missing ; before statement:
typein:2: function g() {z = yield a ? f : x++()}
typein:2: .^
js function g() {(z = yield a ? f : x++)()}


To confirm this, I patched WebKit's Bison grammar for JS to support  
yield //a la// JS1.7. I didn't hook up the semantic actions, just  
verified zero reduce-reduce conflicts. Patch attached below --  
comments welcome (including from you WebKit lurkers :-).


Patching this is harder than I thought it would be. After hacking at  
the Bison grammar a bit, I concede your point about implementation  
difficulty!


Usability still favors the Python approach, at least for yield  
statements.


/be



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-17 Thread Brendan Eich

On May 17, 2009, at 11:00 AM, Brendan Eich wrote:

Bean-counting productions in a traditional bottom-up grammar is also  
silly given how many are required for ES1-3. From the patch, notice  
all the existing specialized NoIn/NoBF/NoNode variants in parser/ 
Grammar.y (NoBF = No Brace at Front, as far as I can tell).


Correction:

%type expressionNode  MemberExpr MemberExprNoBF /* BF = brace or  
function */


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-17 Thread Brendan Eich

On May 17, 2009, at 12:43 PM, Mark S. Miller wrote:

On Sun, May 17, 2009 at 11:00 AM, Brendan Eich bren...@mozilla.com  
wrote:
Analogous to direct vs. indirect eval in ES5 (15.1.2.1.1), 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.


I don't follow. What runtime check? For the eval operator, the runtime
check is whether the value of the eval variable is the original global
eval function. It makes no sense to have a corresponding global yield
function value.


If we reserve yield then you're right. One of the appealing (at least  
to me) aspects of Neil's suggestion was that it would avoid opt-in  
versioning required by reserving yield (which is used in extant web  
content, or was when we tried reserving it without opt-in versioning  
-- the particular use was as a formal parameter name, used as a flag  
not a function).


/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax

2009-05-17 Thread David-Sarah Hopwood
Brendan Eich wrote:
 On May 17, 2009, at 12:43 PM, Mark S. Miller wrote: 
 On Sun, May 17, 2009 at 11:00 AM, Brendan Eich bren...@mozilla.com
 wrote:
 Analogous to direct vs. indirect eval in ES5 (15.1.2.1.1), 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.

 I don't follow. What runtime check? For the eval operator, the runtime
 check is whether the value of the eval variable is the original global
 eval function. It makes no sense to have a corresponding global yield
 function value.
 
 If we reserve yield then you're right. One of the appealing (at least to
 me) aspects of Neil's suggestion was that it would avoid opt-in
 versioning required by reserving yield (which is used in extant web
 content, or was when we tried reserving it without opt-in versioning --
 the particular use was as a formal parameter name, used as a flag not a
 function).

Oh, right. We've been talking at cross-purposes. I assumed that you were
suggesting that 'yield' should be contextually reserved. That is what
I've been saying couldn't work due to ambiguities.

-- 
David-Sarah Hopwood ⚥

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax

2009-05-17 Thread Brendan Eich

On May 17, 2009, at 5:05 PM, David-Sarah Hopwood wrote:


Brendan Eich wrote:

On May 17, 2009, at 12:43 PM, Mark S. Miller wrote:

On Sun, May 17, 2009 at 11:00 AM, Brendan Eich bren...@mozilla.com
wrote:
Analogous to direct vs. indirect eval in ES5 (15.1.2.1.1), 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.


I don't follow. What runtime check? For the eval operator, the  
runtime
check is whether the value of the eval variable is the original  
global
eval function. It makes no sense to have a corresponding global  
yield

function value.


If we reserve yield then you're right. One of the appealing (at  
least to

me) aspects of Neil's suggestion was that it would avoid opt-in
versioning required by reserving yield (which is used in extant web
content, or was when we tried reserving it without opt-in  
versioning --
the particular use was as a formal parameter name, used as a flag  
not a

function).


Oh, right. We've been talking at cross-purposes. I assumed that you  
were

suggesting that 'yield' should be contextually reserved.


Oh, I should have seen that. Thanks for clarifying.



That is what
I've been saying couldn't work due to ambiguities.


RIght, no sane way to reserve yield or another keyword contextually  
(e.g., only in callee position; contextually in the sense of get and  
set in object initialisers).


In JS1.7+, we reserve yield with opt-in version selection via script  
type=...;version=1.7 and the like. In such a script, yield and let  
are reserved the same way the other identifiers are, which is how ES5  
does it (with an extension we've discussed -- the extension where a  
reserved identifier can be used after 'function' -- but that's not  
interesting for this discussion).


/be


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-17 Thread Neil Mix


On May 17, 2009, at 7:01 PM, Brendan Eich wrote:
The mandatory parentheses could be avoided by breaking from Python's  
precedent and making yield a canonical unary (that is,  
high-)precedence operator like delete, !, etc. But then almost any  
algebraic or logical expression computing the value to yield would  
need parentheses, and people would make mistakes such as yield a + b  
where they meant yield(a + b) -- as in Python -- but got yield(a) + b.


I'm going to make the argument that this is about where the  
parenthesis go -- not *if* -- but where.
- we could always allow parenthesis to be dropped when the yield is  
the entire expression of an expression statement or the right-hand  
side of an assignment.
- in my experience with JS 1.7 I almost always had to parenthesize the  
yield expression when it was in some other kind of expression.  An in  
the cases where parenthesis weren't required, I parenthesized anyway  
to avoid ambiguity and maintain coding style consistency.  (And  
because I got tired of predicting incorrectly whether or not parens  
would be required in a particular context.)


So I would argue that there are two syntactical forms of yield, yield  
E  and (yield E), and that the rules regarding the requirement for  
parenthesis are hard to predict (from personal experience).   
Therefore, I argue that it would make sense to simplify a bit:
- the yield E form may be used when it is the entire expression of an  
expression statement

- all other times it must be parenthesized

Which is *kind of* a way of saying, if you're ignoring the send value,  
you don't have to parenthesize.  But if you use the send value, you  
must parenthesize.


And now that we've made clear the definition of parenthesized and non- 
parenthesized forms of yield, we can proceed to argue that yield(E) is  
a valid form of parenthesis, as much so as (yield E).


Pros for yield(E):
- backward compatible
- easier to read (to my eye)
- it feels more correct to me in context of the when-using-send- 
value rule


Pros for (yield E):
- consistent with python
- doesn't present any is-it-a-function? ambiguities

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-17 Thread Brendan Eich

On May 17, 2009, at 11:48 AM, Brendan Eich wrote:


On May 17, 2009, at 11:00 AM, Brendan Eich wrote:

Python differs from JS by having only assignment statements, not  
assignment expressions, which simplifies the problem a bit, as the  
grep output cited above shows.


Of course this makes trouble with automatic semicolon insertion,  
unless assignment statements are split from assignment expressions.  
D'oh!


js function g() {z = yield a ? f : x++()}
typein:2: SyntaxError: missing ; before statement:
typein:2: function g() {z = yield a ? f : x++()}
typein:2: .^
js function g() {(z = yield a ? f : x++)()}


I was wrong, there's no issue here (apart from SpiderMonkey's  
diagnostic being suboptimal). This is not a case of a high-precedence  
prefix operator whose following operand is a low-precedence expression  
non-terminal. That's unsound.


In this example, yield is just like a nested assignment:

js function g() {z = w = a ? f : x++()}
typein:1: SyntaxError: missing ; before statement:
typein:1: function g() {z = w = a ? f : x++()}
typein:1: ...^

where the body (z = w = a ? f : x++()) === (z = (w = (a ? f : x++(.

If PrimaryExpression: yield AssignmentExpression were a production in  
the grammar, then we would have the bug I was worried about, the one  
that Waldemar pointed out let expressions, which also afflicts  
expression closures (ASI makes the bug harder to spot, was Waldemar's  
further point -- but ASI is not an issue here).



Patching this is harder than I thought it would be. After hacking at  
the Bison grammar a bit, I concede your point about implementation  
difficulty!


I still concede greater burden on implementor, but here's an updated  
WebKit/JavaScriptCore/parser patch:





p
Description: Binary data





/be___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-14 Thread Brendan Eich

On May 14, 2009, at 1:14 PM, Neil Mix wrote:


On May 14, 2009, at 2:38 PM, Brendan Eich wrote:

Indeed the low-precedence (same as assignment) nature of the yield  
unary caused JS1.7 to follow Python in requiring parentheses around  
yield expressions in lists: in comma expressions and actual  
parameter lists (although we diverged from Python by allowing an  
unparenthesized yield expression as the last actual argument in a  
call or new expression's parameter list -- Python requires  
foo((yield bar)) instead of foo(yield bar)).


I have this idea that it would be better for yield expressions to  
look like function calls: 'yield' '(' expression? ')'.  (Note that  
this is only a syntactical suggestion; clearly an implementation  
wouldn't actually treat it like a function.)  That would eliminate  
the precedence issues Brendan cites while also making the syntax  
backward compatible with earlier ES parsers.  Is there any technical  
reason why that wouldn't be possible?


The syntax could work but we need to reserve yield contextually. It  
can't be a user-defined function name and a built-in function. The  
compiler must unambiguously know that yield (the built-in) is being  
called in order to make the enclosing function a generator.


This is reason enough in my view to keep yield a prefix operator and  
reserve it. I wish I had done that with eval in JS1.0!


Another reason is your duck/cow point, which I think is a separate  
point from compiler analyzability. Really, no one writes yield(...) in  
Python, and extra parens hurt (I know RSI sufferers who benefit from  
lack of shifting in Python and Ruby).


Now you could argue that we have eval already, and a cheap-ish way to  
detect direct calls to it (see https://mail.mozilla.org/pipermail/es-discuss/2009-January/008656.html) 
, so why not add something like that again? One reason is that the  
cost is not zero -- cheap-ish, not cheap and not free. Adding more  
distinguished special-form instructions that fall back on call  
behavior if the callee is not the magic built-in will annoy  
implementors.


But you do make a good no-new-syntax case, ignoring the above  
considerations. I still don't buy it, given let not being doable the  
same way. We need new keywords and special forms (not many, but it's  
absurd to freeze the set from ES3 in 1999).


/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-14 Thread David-Sarah Hopwood
Brendan Eich wrote:
 On May 14, 2009, at 1:14 PM, Neil Mix wrote:
 
 I have this idea that it would be better for yield expressions to look
 like function calls: 'yield' '(' expression? ')'.  (Note that this is
 only a syntactical suggestion; clearly an implementation wouldn't
 actually treat it like a function.)  That would eliminate the
 precedence issues Brendan cites while also making the syntax backward
 compatible with earlier ES parsers.  Is there any technical reason why
 that wouldn't be possible?
 
 The syntax could work but we need to reserve yield contextually.
 It can't be a user-defined function name and a built-in function. The
 compiler must unambiguously know that yield (the built-in) is being
 called in order to make the enclosing function a generator.
 
 This is reason enough in my view to keep yield a prefix operator and
 reserve it.

But that doesn't help: the argument to yield is an arbitrary expression,
so 'yield (foo)' could be either a function call or a yield-expression.
That means that this approach can at best be no simpler to implement or
specify than the function call syntax.

With the function call syntax, it would be sufficient to keep the
existing ES5 grammar for function calls, and then check after parsing
whether a MemberExpression or CallExpression followed by Arguments is
the string yield. With the operator syntax, it's more complicated
than that because there are more syntactic contexts to consider.

 Another reason is your duck/cow point, which I think is a separate point
 from compiler analyzability. Really, no one writes yield(...) in Python,
 and extra parens hurt (I know RSI sufferers who benefit from lack of
 shifting in Python and Ruby).

Yes, those are separate points that I am not arguing against here.

-- 
David-Sarah Hopwood ⚥

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: yield syntax (diverging from: How would shallow generators compose with lambda?)

2009-05-14 Thread Brendan Eich

On May 14, 2009, at 5:13 PM, David-Sarah Hopwood wrote:


Brendan Eich wrote:

On May 14, 2009, at 1:14 PM, Neil Mix wrote:

I have this idea that it would be better for yield expressions to  
look
like function calls: 'yield' '(' expression? ')'.  (Note that this  
is

only a syntactical suggestion; clearly an implementation wouldn't
actually treat it like a function.)  That would eliminate the
precedence issues Brendan cites while also making the syntax  
backward
compatible with earlier ES parsers.  Is there any technical reason  
why

that wouldn't be possible?


The syntax could work but we need to reserve yield contextually.
It can't be a user-defined function name and a built-in function. The
compiler must unambiguously know that yield (the built-in) is being
called in order to make the enclosing function a generator.

This is reason enough in my view to keep yield a prefix operator and
reserve it.


But that doesn't help: the argument to yield is an arbitrary  
expression,
so 'yield (foo)' could be either a function call or a yield- 
expression.
That means that this approach can at best be no simpler to implement  
or

specify than the function call syntax.


Were you responding to Neil instead of me? I'm not advocating Neil's  
proposal, but it seems to me he's arguing for it to avoid the  
mandatory parentheses around the entire yield expression in almost any  
surrounding expression in which it could be embedded. He is right that  
requiring parentheses around yield's operand avoids mandatory parens  
around yield expressions in list contexts.


Simpler to implement is not the issue, but it's a wash as you say.



With the function call syntax, it would be sufficient to keep the
existing ES5 grammar for function calls, and then check after parsing
whether a MemberExpression or CallExpression followed by Arguments is
the string yield. With the operator syntax, it's more complicated
than that because there are more syntactic contexts to consider.


Yes, but it's not that complicated. SpiderMonkey and Rhino do it. Code  
size burden is in the noise.



Another reason is your duck/cow point, which I think is a separate  
point
from compiler analyzability. Really, no one writes yield(...) in  
Python,

and extra parens hurt (I know RSI sufferers who benefit from lack of
shifting in Python and Ruby).


Yes, those are separate points that I am not arguing against here.


Ok.

I was replying to Neil, not to you (hadn't seen any message from you  
on this sub-thread).


/be




--
David-Sarah Hopwood ⚥

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss