State of the Lambda

Neal Gafter neal at
Wed Jul 7 09:59:37 PDT 2010

On Wed, Jul 7, 2010 at 9:32 AM, Brian Goetz <brian.goetz at> wrote:

> I have posted a "State of the Lambda" document at:
> For convenience, the text is reproduced here (in "markdown" source).

A few comments:

A primary reason that inner classes are imperfect closures is that they are
not lexically scoped, but this reason is not even mentioned.

It isn't clear where function types fit into this.  If you're considering
dropping them, that should be more explicit.  For a variety of reasons, I
believe that would be a mistake.

It isn't clear from this document which contexts would allow inference of
the lambda parameter type.  I suggest it should be supported everywhere.
Disallowing lambda parameter type inference when the lambda is an argument
to an overloaded method will cripple the API designer in a number of common
situations.  Scala and C# (among other languages) have both method
overloading and lambdas in which the lambda argument type may be inferred.
The combination is allowed, and as a practical matter is quite useful.  The
main "disadvantage" is that it is possible to write programs that are
NP-hard to compile <>.
The hard (slow to compile) cases do not arise in practice, so the
disadvantage does not impact the programmer.  The hard part for the
compiler-writer (as usual) is producing good diagnostics.

Adding a "yield" statement doesn't improve the transparency issue with
"return", it just pushes the issue somewhere else.  Your "yield" statement
is not transparent.

It isn't clear how a lambda body is to be analyzed.  Specifically, there is
a chicken-and-egg issue with the type of "this" and overload resolution (and
exception analysis).  The situation is made worse by extension methods and
class SAMs.  For example, consider

  f({ ->; });

The lambda takes no arguments and returns "void", but the exceptions thrown
by "foo" affects the exceptions thrown by the lambda, and therefore affects
the results of overload resolution for "f".  But the results of overload
resolution for "f" defines the type of "this", and therefore controls the
meaning of "foo" and the exceptions thrown by "".  As you can see,
the type of "this" affects the type of the lambda even when not used in a
result expression.  I have no idea what ordering will be implied by the
specification for semantic analysis.

Your statement list syntax is messed up.  It only allows infinite lists.  It
has duplicate semicolons (there is a semicolon as a statement terminator and
a second one between statements).  I can't figure out why you would put an
optional ";" in the lambda body when it follows a statement list; a
statement list can already end with an "empty" statement, so that part of
your syntax introduces an ambiguity.

The logic for disallowing capture of mutable variables doesn't make sense:

It is likely that we will *not* permit capture of mutable local variables.
The reason is that idioms like this:

int sum = 0;
list.forEach({ Element e -> sum += e.size(); });

are fundamentally serial; it is quite difficult to write lambda bodies like
this that do not have race conditions.

Presuming list.forEach is not concurrent (I believe it very unlikely that it
would be) this code has no race conditions.  Lambda expressions are very
useful for improving the organization of parts of the program that are not
concurrent, and that benefit is undermined by restrictions that are
justified by reference concurrency.  Forcing the user to use a final
Reference<Integer> or int[] for the sum variable here doesn't address a race
condition, it simply inconveniences the programmer.  In short, lambdas are
orthogonal to concurrency (they benefit concurrent scenarios as well as
serial ones).

More information about the lambda-dev mailing list