Control structure proxies (aka monads, cps, and their relatives)

Claus Reinke claus.reinke at talk21.com
Mon May 23 12:57:43 PDT 2011


This is just a last-minute plea, given that the proposal freeze is 
apparently imminent: could the committee please reserve a slot 
for solving the "readable monadic coding in Javascript" issue - 
it needs no semantic changes, only syntax, and combining 
technical aspects of existing proposal might be sufficient, but
none of the existing proposals alone seems sufficient to address 
this problem (nor is that that aim of the existing proposals):

-  monadic programming is a modular variant of cps-style code,
    which allows to define purpose-build control structures from 
    the ground up, starting with composing two statements/blocks
    together while binding variables in the second to results from
    the first;

    since the committee is already familiar with the ideas of object
    and value proxies, it might help to think of monads and their
    relatives as control structure proxies; they allow to define
    variants of control structures that are or would need to be
    built-in to Javascript (not just loops and conditionals, but 
    break/continue/exceptions/backtracking search/..) while 
    providing a uniform look and feel for control structures 
    adapted to different problem domains (be it asynchronous 
    code, parsers, constraint programming, workflows, ..);

    it is technically possible to use monadic programming in 
    Javascript, so no semantic extensions are necessary, but when
    the nested callbacks (one per line of proxied code) that are 
    typical for this style are translated to Javascript syntax, the
    results are cumbersome enough to nullify any readability
    advantages - the essence of code is buried in syntactic noise;

    this issue is well-known, has been blogged about in several
    application contexts (not limited to asynchronous code), and 
    has even attracted implementations of a large variety of libraries 
    and pre-processors; in this, the situation is similar to module 
    loaders, both in the unhelpful (for reuse) divergence of styles 
    and in the fact that libraries alone cannot solve the issue; 

    the idea would be to reduce the need for pre-processing, 
    giving library-based approaches a better chance; preferably,
    by making the syntax for function definitions and calls simple
    enough to keep nested callback chains readable; if that 
    doesn't work out, special monad notation could be considered;

Relation to existing proposals/previous discussion:

- block lambdas, though they allow to make single callbacks
    to higher-order functions look like language structures,
    thereby supporting the re-definition of some complex 
    control structures, do not help with user-defined control 
    structures built from smaller building blocks (variable
    binding, statement composition) - they do not reduce
    the amount of brace nesting for nested callback chains,
    although they do aim to reduce the parenthesis nesting
    of function calls;

- arrow functions, especially the implicit expression return
    part, would be a step towards simpler function and callback
    definitions, but that does not quite suffice, function calls
    also need to be simplified (nested callback chains consist
    of alternating function definitions and function calls);

- if block_lambdas make it into ES/next, it would be possible
    to rescue the simple part of arrow functions (expression
    return) - since block_lambdas include blocks as expressions,
    with unambiguous new syntax, the block bodies of the 
    arrow syntax proposal could be dropped, leaving a 
    lightweight syntax proposal;

The block lambda proposal includes paren-free calls, while
the arrow function proposal includes paren-free definitions.
Whichever of the two proposals wins, if the combination of
paren-free calls and paren-free definitions, for the subcase
of expression-returning functions, can make it into ES/next,
the situation for monadic programming patterns would be
improved significantly.

Before arrow functions and block lambdas, I tried to outline
the problems of nested parentheses and braces that result
from nested callbacks, with some suggestions toward a
solution (moving parens and braces outward, where they
may become optional in the usage contexts typical for nested
callback chains - similar to what happens in arrow syntax, but 
also for function calls) - see my 8th of April message in the 
thread "Flattening syntactic tail nests (paren-free, continued)". 

Those suggestions are more awkward than I'd like, the '@'
symbol is apparently wanted elsewhere, and the syntax would 
need to be worked out in the context of ES grammar. But 
either those suggestions or the combination of the syntax
aspects of block lambdas and arrow functions could serve 
as a placeholder for a proper solution, in view of the deadline. 

The placeholder would be separate from the specific proposals 
of block lambdas and arrow functions, and could be accepted 
with a tentative status, subject to it being clarified by the time 
the other proposals settle down.

If there turns out to be no way to solve the issue, which is

    Function definition and call syntax that enables
    readable coding of monadic programming patterns

satisfactorily in JS, by the time the finished proposals get
integrated in the new spec, the placeholder proposal could 
be dropped and forwarded to ES/next/next, but if a solution 
can be worked out in time, based on existing material, it 
would be sad if it foundered on the proposal deadline.

Claus
 


More information about the es-discuss mailing list