return-from-lambda viewed as dangerous, good alternatives
Stephen Colebourne
scolebourne at joda.org
Thu Jan 7 02:12:42 PST 2010
2010/1/7 John Rose <John.Rose at sun.com>:
These points are all good and valid, but I hope that Mark's decision
has closed the debate on this. I'm not arguing that your points aren't
valid, its just that they aren't valid for Java.
Now, other languages, old (Smalltalk) and new (Scala) do manage to
have transparent closures. But this is as part of the holistic vision
for their language. Java's vision is different, and the approaches
that look and feel right in Java are different.
For example, the equivalent to closures in C#, Javascript, Fantom and
C++ all define local returns AFAIK. This is partly about a common
understanding of what works for that category of language (mixture of
statement and expression).
> First, if we were going to do "transparent lambdas" (which I understand we're not, but stay with me a second), adding a new meaning to the "return" keyword obviously interferes with the old meaning, which is "find the enclosing method and return a value from it". You can test this interference by imagining a hapless programmer refactoring code and pasting some stuff containing a "return" statement into a new lambda expression.
The primary set of users of Project Lambda are those moving up from
Java 6. They will know about inner classes (where return is local).
Their primary set of refactoring on receiving JDK 7 will be conversion
of one method inner classes to lambdas. This refactoring would be
broken by non-local returns.
Or to put it another way, the refactoring of "surround this code by a
lambda", aka TCP, isn't the most important refactoring we need to
design for.
> It's no good saying "Aha, but every lambda body is really a method in the VM, so the meaning of 'return' is unchanged." That's a category error. We're designing language here, and it's a mistake to mix in implementation considerations and/or assume the writer of the code is thinking about such implementation considerations when the lambda is being written.
True. But that choice was made many years ago with inner classes.
Today's Java developers, and those using sister languages, understand
the idea of local return - so long as it is clearly visible where the
local return returns to. (And this point is absolutely key!)
> Putting a different sub-language with different rules in lambda bodies would make lambdas too dangerous to use. Imagine again the hapless programmer editing code in and out of lambda bodies. So we give ourselves permission to bend but not break the principle of transparency.
With respect, I believe you have a mental model of lambdas that is
correct and pure (transparent wrappers around code that allow it to
move). Unfortunately, that isn't the mental model that current Java
developers have for a feature like this, nor is it one that fits the
(hand-waving) Java-style (evidenced by other languages approach to the
same problem space). ie. developers know and understand that there are
different rules for code within a single method.
> And, in these terms, every single "return" in the whole world of Java is a bug waiting to happen, as soon as the code it's in starts to be rewritten to include lambdas.
Actually, the opposite is true. With transparent lambdas, a "return"
becomes a very dangerous item, that developers can no longer trust. It
might throw a NonLocalTransferError, which is unexpected and far
harder to grasp than what happens today. Not being able to trust the
"return" keyword is an extremely serious problem, and not one we
should add to Java.
> There's a second reason for not overloading returns, too. An overloaded return not only fails to implement transparency, but it also PREVENTS any future version of Java (or any sister language) from increasing the transparency to include control transfers. To overload "return" is effectively to say "we'll never need uplevel branches in Java". And that is, to put it mildly, short-sighted. If you've ever designed a multiple-purpose language before, you know that any statement beginning "our users will never need..." is almost always false.
True, if you're designing a new language. Java isn't a new language,
its an established, but evolving, one. What already exists in the
language narrows our choices greatly.
I should also note that there are at least three different ways to add
non-local returns from a Project Lambda type solution.
1) Use different syntax for the non-local return - "throw return".
This has the major advantage of making it obvious that something
complicated and risky is occurring (oh and I realise that you may not
see non-local return as complicated and risky - I have to ask you to
understand that many of us do, I'd suggest the majority).
2) Control-invocation syntax changes return to non-local - If you
place the closure block after the method args (control invocation
syntax style), then "return" changes to non-local. This works as an
approach, because the visible return point has now disappeared. And
yes, you might need a new local return syntax here.
3) Add a different language feature. This may be something similar to
lambdas (like the JCA part of FCM), or something different like
hygenic macros. The aim would be to produce something that is distinct
enough from lambdas to be seen as a different construct by developers.
Of course, I'm yet to be convinced that non-local returns will ever be
needed in Java, but I do concur that we should have some plan for how
to implement them were our collective minds to want it. Three plans
seems more than enough :-)
[snip lots of good ideas for alternative local return syntax]
I hope that this discussion can be re-closed by Mark, as we need to
move on to detail.
Stephen
More information about the lambda-dev
mailing list