Allen's lambda syntax proposal

David-Sarah Hopwood david.hopwood at industrial-designers.co.uk
Fri Dec 5 20:07:28 PST 2008


Maciej Stachowiak wrote:
> On Dec 5, 2008, at 10:00 AM, Jon Zeppieri wrote:
> 
>> A label is an escape continuation.  Once control has returned past the
>> point where the continuation was captured, it's dead, and it can't be
>> resumed.
> 
> So return from a lambda is sometimes but not always a runtime error?

That in itself does not seem much of a problem (it doesn't seem to be
in Smalltalk or E).

> Other times it can return through multiple levels of function calls
> without raising an exception? That seems pretty bad for ease of
> understanding and for performance of implementations.

I agree, although I would express this as a safety issue: the safety
hazard is that you may call a lambda without expecting it to perform
a jump within the calling scope. The performance issue is that *all*
calls that are within the scope of a labelled statement or loop must
check for an escape.

There is a possibility for solving both of these issues while still
allowing all of the suggested uses of lambdas. It involves permitting
a given call to perform an escape (that is, break, continue or return)
only if it is explicitly marked as being able to do so. If an unmarked
call would escape, then it instead throws an exception.

For example (syntax intended only as a strawman; I know it is
incompatible to add an 'escape' keyword):

  CallExpression :
    ...
    'escape' CallExpression Arguments

Then a user-defined 'while' could be written as:

  const _while = \(cond, body) {
    // escapes from 'cond' are intentionally disallowed;
    // only 'body' can escape.
    if (cond()) { escape body(); escape while(cond, body); }
  };

and a use of '_while' would be:

  foo: escape _while(\{bar}, \{
    ...
    if (baz) break foo;
  });

This doesn't impede the use of lambdas in control abstractions or
in desugaring, because those uses can easily call the lambda using
an 'escape' call. Nor does it impede "lambda as the new function",
because uses of lambda in place of function won't attempt to 'break',
'continue' or 'return' (and that can be made a static error in the
syntactic contexts where lambda is intended to replace functions,
such as in my suggestion for object literals).

It does introduce the syntactic inconvience of having to call control
abstractions using 'escape' (or whatever syntax is used for these
calls). For use of lambda to desugar built-in constructs, this is
not an issue.

If at some point macros were added (even a very limited form of
macros), then the syntactic inconvience could be alleviated, and
nothing would have to be changed in the semantics of lambda at
that point.

> If you do this:
> 
> [1 2 3].map(lambda (x) { return x + 1; })
> 
> I think it would be better for that to be a syntax error than to make
> the containing function return 2.

In my proposal above, that would be a dynamic error (the call to the
lambda from 'map' would throw an exception).

This case could in principle be detected statically; that is, passing
a lambda expression *directly* as an argument without using 'escape'
would be a static error.

Unfortunately it's not possible to detect all of the errors introduced
by this proposal statically, because the lambda could have been obtained
from anywhere, so without static typing (or making lambdas not-first-class,
which I don't recommend), it's not possible to know in all cases when a
lambda is being passed as an argument.

> It seems to me the current design prioritizes lambda as a desugaring
> construct or building block for imperative-style control flow, over use
> as an actual first-class function. I assume break and continue inside a
> lambda have similar issues.

They do, but the proposal above addresses 'break', 'continue' and 'return'
together.

It may be considered too complicated, too restrictive, or not sufficiently
easy to understand. I'm undecided about that, although it does solve both
the safety and performance objections to escape continuations, and the
semantics are easy to specify.

-- 
David-Sarah Hopwood


More information about the Es-discuss mailing list