Block lambda grammar: BlockArguments

Brendan Eich brendan at mozilla.org
Sat Jan 14 18:31:20 PST 2012


> Axel Rauschmayer <mailto:axel at rauschma.de>
> January 14, 2012 4:58 PM
>
> Three arguments in favor of yanking:
>
> - Thanks to lambdas, setTimeout already looks very nice – even as a 
> parenthesized function call.

Good -- and you make a good case here in terms of paren-counting:

   setTimeout {|arg| ...} (1000) (x)

is worse by paren-count cost than:

   setTimeout({|arg| ...}, 1000, x)

and with the style I expect where there's a space between the setTimeout 
and the {, worse in total character count even including the commas 
required in the second form.

Let B be the number of block-lambdas and I be the number of InitialValue 
expressions. In general we have B spaces (one before each block-lambda) 
and 2I parens and I spaces (one before each parenthesized InitialValue) 
or B+3I overhead with the paren-free syntax in the expected style, vs. 2 
parens around the whole arg list + 2(B+I-1) ", " pairs between args, for 
2(B+I). So the trade-off relation is

paren-free <=> parenthesized
B+3I <=> 2B+2I or
I <=> B

So if I < B, paren-free wins. If I >= B, parenthesized wins by I-B 
chars. This ignores readability trade-off between ", " separation and " 
(" with ")" on the right of each InitialValue.

> - Putting callable values last is more likely, the grammar rule 
> introduces an odd asymmetry, by not allowing leading a leading ( 
> InitialValue ) . I’m not saying that that would be a desirable feature 
> (currying is fine here), just that trailing non-lambdas seem much 
> rarer than leading non-lambdas.

Agreed.
>
> - The counter-argument (*) you mention above weighs heavily. Most 
> people (certainly me) probably expect a function or method call when 
> they see a parenthesized value.

I think you are right.
>
> The following seems like an elegant and easy to understand rule to me:
>     “The parameters of a function or method call are either 
> parenthesized or paren-free. In the latter case, all parameters must 
> be lambdas.”

Given the overhead trade-off relation, I'm ditching the whole ( 
InitialValue ) alternative. Thanks for poking at this!

/be
>
> -- 
> Dr. Axel Rauschmayer
> axel at rauschma.de <mailto:axel at rauschma.de>
>
> home: rauschma.de <http://rauschma.de>
> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
> blog: 2ality.com <http://2ality.com>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> Brendan Eich <mailto:brendan at mozilla.org>
> January 14, 2012 2:41 PM
>> Axel Rauschmayer <mailto:axel at rauschma.de>
>> January 14, 2012 1:32 PM
>>>>       myfunc(arg1, arg2) {|| } {|| }  ~~~>  myfunc(arg1, arg2, {|| 
>>>> }, {|| })
>>>>      myfunc {|| } {|| }  ~~~>  myfunc({|| }, {|| })
>>>
>>> The closing parenthesis after arg2 really ought to mean end of 
>>> formal parameter list. Anything else is too magical.
>>
>> I think that’s how Ruby does it.
> Indeed:
>
> $ ruby
> def foo(a,b)
>   yield a+b
> end
> foo(1,2) {|x| puts x}
> 3D
>
>
>> I’m on the fence. It is indeed quite magical (and not the good kind 
>> of magical).
>
> It's way too magical in my view to retrofit to JS. Again, making "if" 
> and "while" and so on into block-lambda calling functions seems a wild 
> goose chase. These forms take *statements*, not just block-statements 
> (and not block-lambdas to call). They're built into the language via 
> the C-like syntax.
>
> Imitating "if" etc. is fine. It's a motivation for the paren-free and 
> *semicolon-free* CallWithBlockArguments statement form.
>
> And such imitation is doable via the strawman grammar, simply by 
> returning a function (currying a bit). Singletons or pairs can be used 
> if there's no need to retain the "if condition":
>
> function myIf(cond) {
>   // The block-lambdas here are singletons (no upvars)...
>   return cond ? {|t, e| t} : {|t, e| e};
> }
>
> myIf (x > y) {|| "greater"} {|| "not greater"}
>
> Of course, one might want a dummy "else" ("myElse") in between the 
> then and else blocks.
>>
>>> Why should foo(arg1)(arg2) and foo(arg1){||arg2} differ?
>>
>> BlockArguments :
>>     BlockLambda
>>     BlockArguments [no LineTerminator here] BlockLambda
>>     BlockArguments [no LineTerminator here] ( InitialValue )
>>
>> I still don’t fully understand the ( InitialValue ) at the end – it’s 
>> a single value in parens that can come after several blocks. If 
>> Ruby-style magic isn’t an option then I would expect (and prefer) 
>> that there were only two calling “modes”:
>>
>> - Traditional: myfunc(arg1, arg2, ...}
>> - Paren-free – lambdas only: myfunc {|| body1} {|| body2} ...
>
> The objection (if you read the whole thread containing the message I 
> cited, I think you'll find it) was that requiring *only* block-lambdas 
> for the paren-free call form means expression arguments, even ones as 
> simple as numeric literals, must be bracketed by {|| and }. Why not 
> allow ( and ) instead?
>
> One counter-argument is that this looks the argument list of a call 
> expression whose callee is everything to the left. But paren-free call 
> syntax supports newline termination, so I added the ... ( Initial 
> Value ) production to satisfy setTimeout-like use cases without 
> requiring {|| and | as brackets.
>
> If this alternate production bites back in some way, or is simply 
> under-used or too surprising, I'll yank it.
>
> Indeed I could simplify CallWithBlockArguments to take only one 
> BlockLambda argument but that seems unnecessarily restrictive. More 
> comments welcome.
>>
>>>> Following a block with a non-block doesn’t seem like a good idea.
>>> This was an explicit goal, in order to support use-cases including 
>>> setTimeout and promises APIs.
>>
>> With the above I meant: In paren-free mode, following a block with a 
>> non-block doesn’t seem like a good idea. With a normal paren call, I 
>> don’t see any problems.
>
> The consequences might include
>
>   setTimeout {|arg| ...} {|| 1000} {|| x}
>
> That is a bit harsh since 1000 (one second) is a literal and /* 
> compute arg here */ is typically simply a pass-by-value reference to a 
> variable in the scope of this setTimeout call, e.g. x in this example.
>
> The strawman therefore supports
>
>   setTimeout {|arg| ...} (1000) (x)
>
> for example.
>
> Could we go further and support certain primary expressions, namely 
> all of the PrimaryExpression right-hand sides except for object literal?
>
> NonObjectLiteralPrimaryExpression :
>     this
> Identifier
> Literal
> ArrayLiteral
>     ( Expression )
>
> ?
>
> Not a problem grammatically except for the added complexity, and the 
> specific usability issues arising from that slight complexity:
>
> * Leaving out object literal means one must parenthesize an object 
> literal but not an array literal.
> * Allowing K but not K+1, requiring instead (K+1), may blow back with 
> users.
>
> /be
>>
>> -- 
>> Dr. Axel Rauschmayer
>> axel at rauschma.de <mailto:axel at rauschma.de>
>>
>> home: rauschma.de <http://rauschma.de>
>> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
>> blog: 2ality.com <http://2ality.com>
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> Brendan Eich <mailto:brendan at mozilla.org>
>> January 14, 2012 9:41 AM
>>> Axel Rauschmayer <mailto:axel at rauschma.de>
>>> January 13, 2012 9:09 PM
>>>
>>> If I read the grammar correctly, then you can do things such as 
>>> (read "~~~>" as "desugars to"):
>>>
>>>      myfunc {|| } {|| } (arg3) (arg4)  ~~~>  myfunc({|| }, {|| }, 
>>> arg3, arg4)
>>>
>>> The above is a function call with 4 arguments. My wish would be 
>>> different: I would want to put lambdas after a function or method 
>>> call and treat those lambdas as additional arguments:
>>>
>>>      myfunc(arg1, arg2) {|| } {|| }  ~~~>  myfunc(arg1, arg2, {|| }, 
>>> {|| })
>>>      myfunc {|| } {|| }  ~~~>  myfunc({|| }, {|| })
>>
>> The closing parenthesis after arg2 really ought to mean end of formal 
>> parameter list. Anything else is too magical.
>>>
>>> Rationale: I would always make lambdas trailing arguments, similar to
>>>      if (cond) {} {}
>>> And I would rather achieve this effect without currying.
>>
>> Why should foo(arg1)(arg2) and foo(arg1){||arg2} differ?
>>
>> Your use-case is satisfied by returning a function (memoized, 
>> singleton even), but the symmetry between (arg1, ... argN) and 
>> space-separated BlockArguments should not be broken.
>>
>>> Following a block with a non-block doesn’t seem like a good idea.
>>
>> This was an explicit goal, in order to support use-cases including 
>> setTimeout and promises APIs.
>>>
>>> Has the other approach been considered?
>>
>> Yes, see
>>
>> https://mail.mozilla.org/pipermail/es-discuss/2011-May/014675.html
>>
>> /be
>>>
>>> -- 
>>> Dr. Axel Rauschmayer
>>> axel at rauschma.de <mailto:axel at rauschma.de>
>>>
>>> home: rauschma.de <http://rauschma.de>
>>> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
>>> blog: 2ality.com <http://2ality.com>
>>>
>>> Brendan Eich <mailto:brendan at mozilla.org>
>>> January 13, 2012 12:58 PM
>>> Fixed: 
>>> http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival&do=diff
>>>
>>> The LeftHandSideExpression productions and their kids (NewExpression 
>>> and CallExpression) are funky and I keep misremembering how 
>>> NewExpression is what bottoms out via MemberExpression -> 
>>> PrimaryExpression at Identifier.
>>>
>>> /be
>>>
>>> Brendan Eich <mailto:brendan at mozilla.org>
>>> January 12, 2012 11:43 PM
>>>> Brendan Eich <mailto:brendan at mozilla.org>
>>>> January 12, 2012 11:39 PM
>>>>   v.map {|e| e*e}
>>>
>>> Er, not even that -- Arguments required in a CallExpression, so 
>>> v().map or v.map() but not just v.map. Fixes coming tomorrow.
>>>
>>> /be
>>>>
>>>> or
>>>>
>>>>   get_map() {|e| e*e}
>>>>
>>>> or similar. I will fix.
>>>>
>>>> /be
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> es-discuss at mozilla.org
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>> Axel Rauschmayer <mailto:axel at rauschma.de>
>>>> January 12, 2012 11:16 PM
>>>> http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival
>>>>
>>>> I’m trying to understand the syntax:
>>>> BlockArguments :
>>>> BlockLambda
>>>> BlockArguments [no LineTerminator here] BlockLambda
>>>> BlockArguments [no LineTerminator here] ( InitialValue )
>>>>
>>>> - Wouldn’t this allow the following? BlockLambda [no LineTerminator 
>>>> here] BlockLambda
>>>> - InitialValue means that paren-free can be combined with arguments 
>>>> that aren’t blocks, right?
>>>>
>>>> myLoopFunc(initValue1)(initValue2) { | arg1, arg2 | ... }
>>>>
>>>> I think I would prefer the following (IIRC, more like Ruby):
>>>>
>>>> myLoopFunc(initValue1, initValue2) { | arg1, arg2 | ... }
>>>>
>>>>
>>>>
>>> Brendan Eich <mailto:brendan at mozilla.org>
>>> January 12, 2012 11:39 PM
>>>> Axel Rauschmayer <mailto:axel at rauschma.de>
>>>> January 12, 2012 11:16 PM
>>>> http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival
>>>>
>>>> I’m trying to understand the syntax:
>>>> BlockArguments :
>>>>      BlockLambda
>>>>      BlockArguments [no LineTerminator here] BlockLambda
>>>>      BlockArguments [no LineTerminator here] ( InitialValue )
>>>>
>>>> - Wouldn’t this allow the following? BlockLambda [no LineTerminator 
>>>> here] BlockLambda
>>>
>>> Yes.
>>>
>>>> - InitialValue means that paren-free can be combined with arguments 
>>>> that aren’t blocks, right?
>>>
>>> Yes.
>>>>
>>>> myLoopFunc(initValue1)(initValue2) { | arg1, arg2 | ... }
>>>
>>> No, the myLoopFunc(initValue1) is a CallExpression -- see
>>> CallWithBlockArguments :
>>>      CallExpression [no LineTerminator here] BlockArguments
>>>   
>>> The *return value* of that ordinary CallExpression is the callee of the paren-free call.
>>>>
>>>> I think I would prefer the following (IIRC, more like Ruby):
>>>>
>>>> myLoopFunc(initValue1, initValue2) { | arg1, arg2 | ... }
>>>>
>>>
>>> That parses, as described above. The two-argument CallExpression 
>>> must return a function that takes the block arguments.
>>>
>>> I see a problem in the grammar in the strawman, now that you mention 
>>> it: no way to produce a simple identifier callee from 
>>> CallExpression, so no
>>>
>>>   map {|e| e*e}
>>>
>>> only
>>>
>>>   v.map {|e| e*e}
>>>
>>> or
>>>
>>>   get_map() {|e| e*e}
>>>
>>> or similar. I will fix.
>>>
>>> /be
>>> Axel Rauschmayer <mailto:axel at rauschma.de>
>>> January 12, 2012 11:16 PM
>>> http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival
>>>
>>> I’m trying to understand the syntax:
>>> BlockArguments :
>>> BlockLambda
>>> BlockArguments [no LineTerminator here] BlockLambda
>>> BlockArguments [no LineTerminator here] ( InitialValue )
>>>
>>> - Wouldn’t this allow the following? BlockLambda [no LineTerminator 
>>> here] BlockLambda
>>> - InitialValue means that paren-free can be combined with arguments 
>>> that aren’t blocks, right?
>>>
>>> myLoopFunc(initValue1)(initValue2) { | arg1, arg2 | ... }
>>>
>>> I think I would prefer the following (IIRC, more like Ruby):
>>>
>>> myLoopFunc(initValue1, initValue2) { | arg1, arg2 | ... }
>>>
>>>
>>>
>> Axel Rauschmayer <mailto:axel at rauschma.de>
>> January 13, 2012 9:09 PM
>>
>> If I read the grammar correctly, then you can do things such as (read 
>> "~~~>" as "desugars to"):
>>
>>      myfunc {|| } {|| } (arg3) (arg4)  ~~~>  myfunc({|| }, {|| }, 
>> arg3, arg4)
>>
>> The above is a function call with 4 arguments. My wish would be 
>> different: I would want to put lambdas after a function or method 
>> call and treat those lambdas as additional arguments:
>>
>>      myfunc(arg1, arg2) {|| } {|| }  ~~~>  myfunc(arg1, arg2, {|| }, 
>> {|| })
>>      myfunc {|| } {|| }  ~~~>  myfunc({|| }, {|| })
>>
>> Rationale: I would always make lambdas trailing arguments, similar to
>>      if (cond) {} {}
>> And I would rather achieve this effect without currying. Following a 
>> block with a non-block doesn’t seem like a good idea.
>>
>> Has the other approach been considered?
>>
>> -- 
>> Dr. Axel Rauschmayer
>> axel at rauschma.de <mailto:axel at rauschma.de>
>>
>> home: rauschma.de <http://rauschma.de>
>> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
>> blog: 2ality.com <http://2ality.com>
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> Brendan Eich <mailto:brendan at mozilla.org>
>> January 13, 2012 12:58 PM
>> Fixed: 
>> http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival&do=diff
>>
>> The LeftHandSideExpression productions and their kids (NewExpression 
>> and CallExpression) are funky and I keep misremembering how 
>> NewExpression is what bottoms out via MemberExpression -> 
>> PrimaryExpression at Identifier.
>>
>> /be
>>
>> Brendan Eich <mailto:brendan at mozilla.org>
>> January 12, 2012 11:43 PM
>>> Brendan Eich <mailto:brendan at mozilla.org>
>>> January 12, 2012 11:39 PM
>>>   v.map {|e| e*e}
>>
>> Er, not even that -- Arguments required in a CallExpression, so 
>> v().map or v.map() but not just v.map. Fixes coming tomorrow.
>>
>> /be
>>>
>>> or
>>>
>>>   get_map() {|e| e*e}
>>>
>>> or similar. I will fix.
>>>
>>> /be
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>> Axel Rauschmayer <mailto:axel at rauschma.de>
>>> January 12, 2012 11:16 PM
>>> http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival
>>>
>>> I’m trying to understand the syntax:
>>> BlockArguments :
>>> BlockLambda
>>> BlockArguments [no LineTerminator here] BlockLambda
>>> BlockArguments [no LineTerminator here] ( InitialValue )
>>>
>>> - Wouldn’t this allow the following? BlockLambda [no LineTerminator 
>>> here] BlockLambda
>>> - InitialValue means that paren-free can be combined with arguments 
>>> that aren’t blocks, right?
>>>
>>> myLoopFunc(initValue1)(initValue2) { | arg1, arg2 | ... }
>>>
>>> I think I would prefer the following (IIRC, more like Ruby):
>>>
>>> myLoopFunc(initValue1, initValue2) { | arg1, arg2 | ... }
>>>
>>>
>>>
> Axel Rauschmayer <mailto:axel at rauschma.de>
> January 14, 2012 1:32 PM
>>>       myfunc(arg1, arg2) {|| } {|| }  ~~~>  myfunc(arg1, arg2, {|| 
>>> }, {|| })
>>>      myfunc {|| } {|| }  ~~~>  myfunc({|| }, {|| })
>>
>> The closing parenthesis after arg2 really ought to mean end of formal 
>> parameter list. Anything else is too magical.
>
> I think that’s how Ruby does it. I’m on the fence. It is indeed quite 
> magical (and not the good kind of magical).
>
>> Why should foo(arg1)(arg2) and foo(arg1){||arg2} differ?
>
> BlockArguments :
>     BlockLambda
>     BlockArguments [no LineTerminator here] BlockLambda
>     BlockArguments [no LineTerminator here] ( InitialValue )
>
> I still don’t fully understand the ( InitialValue ) at the end – it’s 
> a single value in parens that can come after several blocks. If 
> Ruby-style magic isn’t an option then I would expect (and prefer) that 
> there were only two calling “modes”:
>
> - Traditional: myfunc(arg1, arg2, ...}
> - Paren-free – lambdas only: myfunc {|| body1} {|| body2} ...
>
>>> Following a block with a non-block doesn’t seem like a good idea.
>> This was an explicit goal, in order to support use-cases including 
>> setTimeout and promises APIs.
>
> With the above I meant: In paren-free mode, following a block with a 
> non-block doesn’t seem like a good idea. With a normal paren call, I 
> don’t see any problems.
>
> -- 
> Dr. Axel Rauschmayer
> axel at rauschma.de <mailto:axel at rauschma.de>
>
> home: rauschma.de <http://rauschma.de>
> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
> blog: 2ality.com <http://2ality.com>
>
> Brendan Eich <mailto:brendan at mozilla.org>
> January 14, 2012 9:41 AM
>> Axel Rauschmayer <mailto:axel at rauschma.de>
>> January 13, 2012 9:09 PM
>>
>> If I read the grammar correctly, then you can do things such as (read 
>> "~~~>" as "desugars to"):
>>
>>      myfunc {|| } {|| } (arg3) (arg4)  ~~~>  myfunc({|| }, {|| }, 
>> arg3, arg4)
>>
>> The above is a function call with 4 arguments. My wish would be 
>> different: I would want to put lambdas after a function or method 
>> call and treat those lambdas as additional arguments:
>>
>>      myfunc(arg1, arg2) {|| } {|| }  ~~~>  myfunc(arg1, arg2, {|| }, 
>> {|| })
>>      myfunc {|| } {|| }  ~~~>  myfunc({|| }, {|| })
>
> The closing parenthesis after arg2 really ought to mean end of formal 
> parameter list. Anything else is too magical.
>>
>> Rationale: I would always make lambdas trailing arguments, similar to
>>      if (cond) {} {}
>> And I would rather achieve this effect without currying.
>
> Why should foo(arg1)(arg2) and foo(arg1){||arg2} differ?
>
> Your use-case is satisfied by returning a function (memoized, 
> singleton even), but the symmetry between (arg1, ... argN) and 
> space-separated BlockArguments should not be broken.
>
>> Following a block with a non-block doesn’t seem like a good idea.
>
> This was an explicit goal, in order to support use-cases including 
> setTimeout and promises APIs.
>>
>> Has the other approach been considered?
>
> Yes, see
>
> https://mail.mozilla.org/pipermail/es-discuss/2011-May/014675.html
>
> /be
>>
>> -- 
>> Dr. Axel Rauschmayer
>> axel at rauschma.de <mailto:axel at rauschma.de>
>>
>> home: rauschma.de <http://rauschma.de>
>> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
>> blog: 2ality.com <http://2ality.com>
>>
>> Brendan Eich <mailto:brendan at mozilla.org>
>> January 13, 2012 12:58 PM
>> Fixed: 
>> http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival&do=diff
>>
>> The LeftHandSideExpression productions and their kids (NewExpression 
>> and CallExpression) are funky and I keep misremembering how 
>> NewExpression is what bottoms out via MemberExpression -> 
>> PrimaryExpression at Identifier.
>>
>> /be
>>
>> Brendan Eich <mailto:brendan at mozilla.org>
>> January 12, 2012 11:43 PM
>>> Brendan Eich <mailto:brendan at mozilla.org>
>>> January 12, 2012 11:39 PM
>>>   v.map {|e| e*e}
>>
>> Er, not even that -- Arguments required in a CallExpression, so 
>> v().map or v.map() but not just v.map. Fixes coming tomorrow.
>>
>> /be
>>>
>>> or
>>>
>>>   get_map() {|e| e*e}
>>>
>>> or similar. I will fix.
>>>
>>> /be
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>> Axel Rauschmayer <mailto:axel at rauschma.de>
>>> January 12, 2012 11:16 PM
>>> http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival
>>>
>>> I’m trying to understand the syntax:
>>> BlockArguments :
>>> BlockLambda
>>> BlockArguments [no LineTerminator here] BlockLambda
>>> BlockArguments [no LineTerminator here] ( InitialValue )
>>>
>>> - Wouldn’t this allow the following? BlockLambda [no LineTerminator 
>>> here] BlockLambda
>>> - InitialValue means that paren-free can be combined with arguments 
>>> that aren’t blocks, right?
>>>
>>> myLoopFunc(initValue1)(initValue2) { | arg1, arg2 | ... }
>>>
>>> I think I would prefer the following (IIRC, more like Ruby):
>>>
>>> myLoopFunc(initValue1, initValue2) { | arg1, arg2 | ... }
>>>
>>>
>>>
>> Brendan Eich <mailto:brendan at mozilla.org>
>> January 12, 2012 11:39 PM
>>> Axel Rauschmayer <mailto:axel at rauschma.de>
>>> January 12, 2012 11:16 PM
>>> http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival
>>>
>>> I’m trying to understand the syntax:
>>> BlockArguments :
>>>      BlockLambda
>>>      BlockArguments [no LineTerminator here] BlockLambda
>>>      BlockArguments [no LineTerminator here] ( InitialValue )
>>>
>>> - Wouldn’t this allow the following? BlockLambda [no LineTerminator 
>>> here] BlockLambda
>>
>> Yes.
>>
>>> - InitialValue means that paren-free can be combined with arguments 
>>> that aren’t blocks, right?
>>
>> Yes.
>>>
>>> myLoopFunc(initValue1)(initValue2) { | arg1, arg2 | ... }
>>
>> No, the myLoopFunc(initValue1) is a CallExpression -- see
>> CallWithBlockArguments :
>>      CallExpression [no LineTerminator here] BlockArguments
>>   
>> The *return value* of that ordinary CallExpression is the callee of the paren-free call.
>>>
>>> I think I would prefer the following (IIRC, more like Ruby):
>>>
>>> myLoopFunc(initValue1, initValue2) { | arg1, arg2 | ... }
>>>
>>
>> That parses, as described above. The two-argument CallExpression must 
>> return a function that takes the block arguments.
>>
>> I see a problem in the grammar in the strawman, now that you mention 
>> it: no way to produce a simple identifier callee from CallExpression, 
>> so no
>>
>>   map {|e| e*e}
>>
>> only
>>
>>   v.map {|e| e*e}
>>
>> or
>>
>>   get_map() {|e| e*e}
>>
>> or similar. I will fix.
>>
>> /be
>> Axel Rauschmayer <mailto:axel at rauschma.de>
>> January 12, 2012 11:16 PM
>> http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival
>>
>> I’m trying to understand the syntax:
>> BlockArguments :
>> BlockLambda
>> BlockArguments [no LineTerminator here] BlockLambda
>> BlockArguments [no LineTerminator here] ( InitialValue )
>>
>> - Wouldn’t this allow the following? BlockLambda [no LineTerminator 
>> here] BlockLambda
>> - InitialValue means that paren-free can be combined with arguments 
>> that aren’t blocks, right?
>>
>> myLoopFunc(initValue1)(initValue2) { | arg1, arg2 | ... }
>>
>> I think I would prefer the following (IIRC, more like Ruby):
>>
>> myLoopFunc(initValue1, initValue2) { | arg1, arg2 | ... }
>>
>>
>>
> Axel Rauschmayer <mailto:axel at rauschma.de>
> January 13, 2012 9:09 PM
>
> If I read the grammar correctly, then you can do things such as (read 
> "~~~>" as "desugars to"):
>
>      myfunc {|| } {|| } (arg3) (arg4)  ~~~>  myfunc({|| }, {|| }, 
> arg3, arg4)
>
> The above is a function call with 4 arguments. My wish would be 
> different: I would want to put lambdas after a function or method call 
> and treat those lambdas as additional arguments:
>
>      myfunc(arg1, arg2) {|| } {|| }  ~~~>  myfunc(arg1, arg2, {|| }, 
> {|| })
>      myfunc {|| } {|| }  ~~~>  myfunc({|| }, {|| })
>
> Rationale: I would always make lambdas trailing arguments, similar to
>      if (cond) {} {}
> And I would rather achieve this effect without currying. Following a 
> block with a non-block doesn’t seem like a good idea.
>
> Has the other approach been considered?
>
> -- 
> Dr. Axel Rauschmayer
> axel at rauschma.de <mailto:axel at rauschma.de>
>
> home: rauschma.de <http://rauschma.de>
> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
> blog: 2ality.com <http://2ality.com>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120114/1060f39e/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: postbox-contact.jpg
Type: image/jpeg
Size: 1222 bytes
Desc: not available
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120114/1060f39e/attachment-0002.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: postbox-contact.jpg
Type: image/jpeg
Size: 1290 bytes
Desc: not available
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120114/1060f39e/attachment-0003.jpg>


More information about the es-discuss mailing list