Claus,

Thanks for the suggestions. Let me see if I can summarize them and respond 
briefly:

* functions with expression bodies

This was proposed for ES4 and implemented in SpiderMonkey. I believe there are 
some unfortunate ambiguities in the grammar that came up, and I think they've 
been treated as moribund. But I love them, and would love it if we could find a 
way to bring them back in a way that didn't break the grammar.

* using @ for infix function application

I'm pretty skeptical. I don't see it solving any major problems. The @ sigil is 
wanted for many other purposes, so I'm loath to give it up for something that 
isn't incredibly compelling.

* curried function definitions

This seems potentially do-able. I don't think there's necessarily huge demand 
for it, but I'm cautiously open to the idea. We'd have to think through the 
consequences for the grammar pretty carefully.

* functions with expression bodies using => as a separator

Now we're in bikeshedding territory. At the risk of upsetting people, I just 
have to say that I don't have enough time in my life to participate in more 
es-discuss mega-threads on surface syntax.

* making nested callbacks better via all of the above

I think this is a deeper problem that can't be solved with cosmetics. This is 
why I've worked on generators as a good solution for the nested-callback 
problem. 

Dave

On Apr 8, 2011, at 3:42 AM, Claus Reinke wrote:

> In my previous post, I suggested tail nests as a profitable target for 
> reducing reducing parens and braces that distract from common code patterns. 
> I made two concrete suggestions, to
> make both braces around function bodies and parens around
> function applications optional.
> 
> The combination of both suggestions would allow to reduce
> the nesting of parens and braces in tail nests, such as nested callbacks 
> (function definition nested in function application
> argument nested in ..). For the running example, this was
> successful, but rather odd looking - it should be possible
> to do better.
> 
> So I would like to modify those suggestions, to bring them more in line with 
> Javascript practice and Harmony directions.
> As a bonus, the modified suggestions simplify another common
> case of nesting, namely curried function definitions.
> 
>> [mnemonic summary of old suggestions, to be modified]
>> 
>> Suggestion 1 (optional braces around function bodies): 
>>   '(function (..) ..)' may be used instead of 'function (..) {..}'
>> 
>> Suggestion 2 (optional parens around function applications):
>> 
>>   '(f @ a1, .. , an)' may be used instead of  'f(a1,..,an)'
> 
> Suggestion 2 is especially problematic if the argument list
> has more than one component: the hope was that we might later get rid of the 
> commas as well, assuming that
> argument lists are argument tuples, which could become individual arguments 
> by currying. However, I've come to think that this underlying assumption does 
> not fit Javascript: 
> With optional arguments and unbounded lengths, argument lists are really 
> argument arrays - they do not stand for multiple arguments (Javascript has 
> curried functions for that), they each stand for a single argument with an 
> unspecified number of components. We just use them for multiple arguments 
> because
> curried function definitions are so awkward.
> 
> Harmony changes, such as formal parameter destructuring and spreads, will 
> remove the differences in feature sets between
> argument lists and arrays, making it possible to replace
> 
>   'f(a1,..,an)' and 'function f(a1,..,am) {..}'
> 
> with 
>   'f([a1,..,an])' and 'function f([a1,..,am]) {..}'
> 
> at which point the parens will be redundant and each argument
> list can be a proper array (dear arguments: I want my syntax back!-). So this 
> part is well in hand already, and trying to break up those argument list 
> arrays in other ways would go against the direction Harmony is taking.
> 
> Also, the language already provides for curried function definitions and 
> applications, they just don't get used much
> yet. Curried applications are easy, but curried definitions
> happen to be very awkward, syntactically.
> 
> My modified suggestions take both curried functions and
> argument lists as arrays into account, so they do a little less work on 
> applications, making better use of existing syntax, and a little more work on 
> definitions, hoping to give curried definitions a lift.
> 
> What I'd like is to be able to replace the horrible
> 
>   function (..) { return function (..) { .. }}
> 
> with the shorthand notation
> 
>   function (..)(..) { .. }
> 
> (and, similarly, '#(..)(..){..}' instead of '#(..){ #(..){..}}')
> 
> giving curried function definitions the same short syntax
> as curried function applications. This shorthand makes it
> obvious that each argument list really is just a single, complex argument to 
> the function. There are a few obvious problems which would have made this 
> difficult before
> Harmony:
> 
>   - using the outer function's arguments pseudo-array
>       in the inner function's body;
>              Harmony's spreads avoid that problem entirely.
> 
>   - using the outer function's 'this' in the inner function's
>       body (the shorthand notation no longer has an outer
>       function body in which to rename 'this' to 'self'); 
>       this is being addressed in other threads here, so        Harmony is 
> likely to offer at least one solution
>       (optional naming for the implicit argument 'this').
> 
>   - if the formal parameters can consist of multiple
>       argument lists, the beginning of the function body
>       is no longer unambiguous without those braces;
>       to address this, we need an explicit syntactic marker
>       at the boundary between arguments and body;
> 
>       from the archives, it seems that '=>' has been a
>       fairly popular suggestion (usually instead of a prefix
>       marker), so I'll adopt that, but without removing the
>       prefix marker, be it 'function' or '#'.
> 
> Which results in the following modified suggestions
> 
> // --------------------------------------------------
> // Modified suggestion 1 (function definitions): 
>   1a (curried definition shorthand)   
>           function (..)(..) { .. }
> 
>       may be used instead of
> 
>           function (..) { return function (..) { .. }}
> 
>       for arbitrary nestings.
> 
>   1b (function bodies)
> 
>           (function (..)..(..) => ..)
> 
>       may be used instead of 
>           function (..)..(..) {..}
> 
>       (the outer parens are _not_ part of the function definition
>        syntax - they indicate that the source context delimits the
>        function definition from the outside: if the construct in
>        which the definition is nested ends, so does the definition) 
>   1c (ASI needs to know about 1b's implicit block endings)
> 
> // --------------------------------------------------
> // Modified suggestion 2 (function applications):
> 
>       (f @ x)
> 
>   may be used instead of
> 
>       f(x)
> 
>   (the outer parens are _not_ part of the function application
>    syntax - they indicate that the source context delimits the
>    function application from the outside: if the construct in
>    which the application is nested ends, so does the application) 
>   '@' is now just a left-associative infix operator (same    precedence as 
> function application), so
> 
>       (f @ x @ y @ z)
> 
>   is
> 
>       (((f @ x) @ y) @ z)
> 
>   which is
> 
>       f (x) (y) (z)
> 
>   (ideally, infix function application would just be juxtaposition,
>     ie, the parens around single-component argument lists
>     would be optional, without requiring an explicit operator)
> 
> // --------------------------------------------------
> 
> The effect on our running example, in terms of removing
> redundant parens and braces, can be similar, but that
> now needs support from the libraries: they would need to
> curry their API functions so that the callback becomes a
> second, separate argument (instead of the last component
> in a single complex argument list). 
> (mainWindow.menu("File") @ function(file) =>
> file.openMenu @ function(menu) =>
>   menu.item("Open") @  function(item) =>
>     item.click @ function() =>
>       mainWindow.getChild(type('Window')) @            function(dialog) =>
>             ...
> );
> 
> // Note: since function definitions extend as far as possible,
> // to the closing paren here, the inner '@' are unambiguosly
> // nested
> 
> These modified suggestions are simpler, more in line with
> Harmony's directions, and help to reduce the syntactic noise
> for two common sources of nesting: curried definitions and
> definitions as callback arguments.
> 
> Comments, please?-)
> Claus
> _______________________________________________
> 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

Reply via email to