Lambda Conversion Considered Harmful?

Joshua Bloch jjb at google.com
Thu Feb 18 20:58:01 PST 2010


As I'm sure you're aware, I'm very much in favor of the goal of the Lambda
conversion: the new syntax (or something like it) should be usable in
combination with existing constructs that require a "function object" such
as a Comparator or (perhaps) a TimerTask.  But I'm increasingly skeptical
that the Lambda conversion (as described in the proposal) is the best way to
achieve this.

I'm skeptical for two reasons. The first concerns the semantics. Simply put,
function types just get in the way when what you want is a SAM type. They
raise all sorts of thorny issues, many of which we've been discussing
recently. Is the function-typed object the same object as the SAM-typed
object, or are there two objects involved? Is there any way to access the
members of the SAM type? And so on.

The second reason I'm skeptical concerns performance.  The latest spec draft
says this:

Implementing lambda conversion will likely generate new objects to wrap or
> delegate to the lambda expression. This is acceptable in assignment and
> method invocation conversion contexts, but not in a casting conversion
> context. (See
> http://mail.openjdk.java.net/pipermail/lambda-dev/2010-January/000449.html
> )


I fear that this will have disastrous performance consequences. Presented
with a lovely new syntax, programmers will naturally use it, e.g., to make
Comparators:

    Arrays.sort(a, #(String s1, String s2)(return s1.length - s2.length));

But the comparator's sole method is invoked in the inner loop of the sort!
The slowdown caused by the delegation will add to the constant factor of the
(n log n) sort. This could be very costly! I believe it violates a
fundamental tenet of Java's design, which has been called *transparency*:
 magic should be kept to a minimum, and the code should reflect its
performance (to the extent that that's feasible in this day and age). The
for-each loop, by contrast, does not create an Iterator when traversing an
array, so it runs as fast as the traditional for loop that it replaces. This
was very important to me when we were designing the for-each construct, and
I'm glad we did it the way we did.

Therefore, I think we should *very *seriously consider an alternative design
that uses a slightly different syntax when furnishing instances of SAM types
that it does when furnishing instances of function types.  Call them
SAM-lambdas and function-lambads (for the time being). Perhaps the SAM
lambdas could take the type as a mandatory argument, to simplify the
compiler's job:

    Arrays.sort(a, #Comparator(String s1, String s2)(return s1.length -
s2.length));

I have no idea whether this is the best syntax, or even an acceptable
syntax.  The important point is that we need something that:

   (1) Interoperates with existing methods that require "function objects"
   (2) Provides performance equal to current idioms, and
   (3) Provide conciseness close to that of lambdas (as specified in the
current proposal)

As a clarification, I am not arguing for the elimination of function types;
rather I'm arguing that they get in the way of "interoperable function
objects." so we need two separate syntaxes, one for function types and one
for SAM types.

             Josh


More information about the lambda-dev mailing list