optional "function" keyword

Claus Reinke claus.reinke at talk21.com
Sat Mar 10 08:18:36 PST 2012


Like many others, I would like to have very lightweight function definition
and call syntax, because those are the cornerstones of functional 
abstraction.

This transcends classical functions, and would ideally include the ability 
to
*define*, in userland, many of the control-flow constructs that currently 
need
to be built in to the language, like iterators or non-local returns.

The present discussion, and mulling over control-flow abstractions in JS,
reminds me that Javascript is not friendly towards functional abstraction.
Even with short functions, we would still run into trouble at every corner,
such as:

- JS code tends to be statement-oriented, not expression-oriented
- blocks of statements get run when they are encountered, unless wrapped
    by eta-expansion (which then leads to lots of explicit unwrapping calls)
- References cannot be passed as function parameters
- APIs, including core language APIs, tend to be imperative in nature

In light of this, the ideal of lightweight expression-oriented functions
might not be sufficient, even if we could agree on the language constructs.

For instance, I would like my abstractions to work both with expressions
and with statement blocks, meaning implicit returns, and possibly
non-local binding of explicit returns. I definitely do not want to worry
about implicit 'this' or 'arguments' getting in the way. Which looks
a lot like block lambdas, even though I don't like the non-local returns!

So, while I haven't changed my long-term views about what comprises
a good programming language (*), I'm coming around to the view that
block lambdas, with implicit return, might be a good stopgap measure
for JS now, both to make progress, and to fit the ideal of control-flow
abstractions to the realities of JS.

I'd like to encourage other fp fans in this discussion to consider whether
block lambdas might serve their needs, and to list detailed objections
with a view to improving block-lambdas instead of rejecting them with
a generic "this isn't what I'm used to";-)

One thing that block-lambdas don't solve is callback nesting

> The sweet spot that I'm aiming for is to make the callback syntax/
> semantics better, e.g:
>
> IO.readText(path).then((text, err) => {
>    // Many statements in here, including:
>    this.whatever();
> });

I have been playing with 'let'-sugar for the common 'then' callback
pattern, by replacing

    { let param <- rhs; body }
with
    rhs.then( {| param | body } )

Pronounce this as "let param from rhs in body" (it is inspired
by computation expressions in F# and do-notation in Haskell).

Kevin's example would become

    let (text,err) <- IO.readText(path)
    // Many statements in here, including:
    this.whatever();

making asynchronous API usage similar to synchronous usage.

I've found desugaring to short or other functions problematic
(see list above) and don't know yet whether desugaring to
block lambdas solves these issues, but I'd like to throw the
idea into the room, for everyone to play with.

Claus

(*) I would still prefer JS to become more functional, where
functional abstraction, expression-oriented programming, and user-
defined control abstractions are as commonplace as in Haskell, say.
But ES6 not including any progress here (no short functions, no
block lambdas) would be the worst possible result.
 



More information about the es-discuss mailing list