
Java 8 lambda syntax decided - same as C# and Scala - tomeast
http://mail.openjdk.java.net/pipermail/lambda-dev/2011-September/003936.html
======
zmmmmm
Nice to see pragmatism playing a role here. A big problem with Java has always
been the "design by committee" nature of it where we end up with some
theoretical best case that satisfies everyone's egos but turns out to utterly
suck when used in practice.

From another point of view ... it's a shame we needed so many years to come up
with "let's do it like C#".

~~~
bad_user
It's also a shame they haven't done so with other features -- like getting rid
of checked exceptions.

~~~
xtracto
Can you expand on why would you like to get rid of checked exceptions?

~~~
grahamedgecombe
It often leads people to write code like this:

    
    
        try {
            // do stuff
        } catch (TheCheckedException ex) {
            // ignore it
        }
    

then the code continues even though it could be in a bad state if an exception
did occur.

It's a much better solution to let it propagate up the call stack until it can
be dealt with appropriately (e.g. by ending the application, giving a 503
error on a web page request, etc.) Unchecked exceptions will propagate up the
call stack by default if you don't do anything, making it harder for people to
write bad exception handling code.

~~~
Sandman
So add a 'throws' clause to the method in which you call the code that throws
the checked exception and it will propagate upward.

~~~
brlewis
Yes, this! The most irritating debugging I've had to do in Java code is when
someone catches an exception, but fails to handle it effectively, resulting in
another exception being thrown later. If you don't know how to handle it
effectively, just add the 'throws' clause. It's less typing than try/catch, so
I don't understand why people choose to make extra work for themselves and for
me.

I see a lot of comments here that seem to assume catching the exception is the
only option.

~~~
davedx
Exactly. In Eclipse it's so ridiculously easy to make the method pass it on by
adding the throw to your method. I find checked exceptions really useful every
day :)

------
fosk
Finally a decision was made. The decisional process is too slow, this is why
Java in 2011 still misses those features that languages like C# already
support since years.

------
thurn
Excellent to have this finally resolved. I'm sad to not see something a little
closer to the ruby block syntax like in some of the early proposals, though.
Special syntax for lambdas as the last argument to a function lets you write
very readable code for a host of useful cases.

~~~
raganwald
Nota Bene: A Ruby Block is _not_ the same thing as a Ruby Lambda, although
conversion between them is easy. Yielding to a block has somewhat different
semantics than calling a lambda, especially with respect to non-local return.

------
shawndumas
"Mistakes will be made, but that's good because it means decisions are being
made." -- Steve Jobs

~~~
shriphani
How is this a mistake ?

~~~
yzhengyu
Erm, its not?. Shawndumas was just pointing out that a decision was finally
made. They were grappling over the syntax for over two three years.

Now they will just need to grapple over with what kind of scoping that Java's
lambdas will have.

~~~
revertts
I think stating it that way trivializes the amount of work that _has_ gone
into lambdas. There's been a lot of other, more fundamental things discussed
over that 2-3 year period about their implementation; way more than syntax.

~~~
wanorris
What in particular? (Java isn't my primary language, so I haven't been
following this.)

Do you mean about how lambdas are implemented from a bytecode standpoint, or
other types of issues?

~~~
bermanoid
Yes, to some extent there were debates about how the implementation would
work, but also about how they would interact with all the various other
features of Java, most of which were not constructed with lambdas in mind:
generics, exceptions, inheritance, and so on, not to mention lots of fights
over the syntax.

For instance, there was a long battle over whether () would be enough to
invoke a lambda, or whether some sort of apply() or invoke() or .() method
would be required, and a lot of the problems with () come down to differences
between the way fields and methods are inherited in Java, esp. w.r.t.
shadowing. I don't even know how it all came down, but it gets nasty, a lot of
this stuff just wasn't designed with lambdas in mind.

------
jinushaun
Good. The lambda syntax in C# rocks and is a natural fit for Java considering
the origin of C#.

~~~
jpitz
Object Pascal?

------
BDFL_Xenu
I see that the proposed lambda expressions can omit type annotations on the
parameters. Does that mean that Java 8 will have at least some limited form of
type inference?

~~~
spullara
The single abstract method interface type of a lambda will be inferred by its
declaration site.

~~~
umjames
Will they be full closures and remember the state of objects in scope?

~~~
BDFL_Xenu
If they will be based on anonymous inner classes, then yes, they'll capture
the variables from the surrounding scope. Those variables however will be
'final', which means that you can't re-assign them, even if their values are
still liable to side-effects (e.g. setting fields, mutating collections, etc).

~~~
spullara
They are not based on anonymous inner classes (the implementation is likely to
be much different) but they have the same restrictions as BDFFL_Xenu
described.

------
calebmpeterson
try { // for a really long time } finally { // made a decision }

~~~
vorg
There's a JVM language out there that initially allowed try-statements without
catch or finally clauses, e.g

    
    
        try{
          //for a short time only to decide
        }
    

But one of its despots, five years after the language was first released,
changed the syntax to make a catch or finally clause compulsory, e.g

    
    
        try{
          //for a short time to decide
        }finally{}
    

Because I had used these standalone try-statements a lot, I had to go thru all
my code and add empty finally statements to them all.

Scala, on the other hand, still allows standalone try-statements. And Scala
and C# also have a better closure syntax than that language, and are more
worthy to be copied by Java 8.

~~~
ddlatham
What benefits does an empty try block give you? You can always use braces to
separate a block without try at all.

~~~
vorg
> What benefits does an empty try block give you?

An empty try block allows us to repeat variable declarations with the same
name in a long stretch of scripty-style code.

> You can always use braces to separate a block without try at all.

You can use braces in Java, but not in that language I'm talking about: it'll
throw an error saying "Ambiguous expression could be a parameterless closure
expression, an isolated open code block, or it may continue a previous
statement; solution: Add an explicit parameter list, e.g. {it -> ...}, or
force it to be treated as an open block by giving it a label, e.g. L:{...},
and also either remove the previous newline, or add an explicit semicolon
';'".

The standalone-try looked far more elegant than:

    
    
        dudlabel:{
          //do something
        }
    

Better for that despot to re-enable standalone try-statements in Groovy than
petitioning the Java 8 designers that thin arrows look better than industry-
standard thick arrows.

~~~
mattgreenrocks
> An empty try block allows us to repeat variable declarations with the same
> name in a long stretch of scripty-style code.

Either I'm missing something here, or this is really as bad as it sounds.

I understand you want nested scopes that end before the method's scope ends,
but cannot for the life of me think of a defensible code example. Why not just
make them into methods?

~~~
vorg
I did say scripty code. My typical scripting session from scratch starts with
opening a simple editor and starting to type in code. The structure is loose,
perhaps it's testing something I've written in another file in a statically-
typed language. As the code evolves, I slowly give it more structure by
reworking it. At some stage I MIGHT put some code into methods.

But before that stage, nested scopes are useful because I'm _far less likely_
to pass the wrongly-named variable into a function when I'm cutting and
pasting code. An example coding snippet...

    
    
        def out= new File("blah")
        try{
          def testdata= "abcdefg"
          def result= SomethingToTest(testdata, out)
          assert result == result.getSth()
        }
        try{
          def testdata= "hijk"
          try{
            def result= SomethingToTest(testdata, out)
            assert result == result.getSth()
          }
          try{
            def result= SomethingToTest(testdata)
            assert result == result.getSth()
          }
        }
    

If I use testdata1, testdata2, result1, result2, etc, I might forget to rename
a variable after cutting and pasting, and think a test works when it doesn't.

~~~
Torn
Why not just use braces? Take all your 'try' keywords out and the scope
limitations are the same.

Unless you're relying on the try {} to avoid bombing when there are assertion
errors? That just seems a bad way of doing unit testing.

~~~
vorg
You can do that in Java but not in Groovy unless you write

    
    
        tr:{
          //...
        }

------
MatthewPhillips
Lambdas are a lot of fun on C#.

new Thread( => { doStuff(); }).Start();

~~~
linuxhansl
Big deal:

    
    
        new Thread(new Runnable() { public void run() {doStuff();} }).start();

~~~
ppog
But for a small function (which a lambda typically is), the syntactic overhead
of "new Runnable() { public void run()" swamps the actual logic. When I read
this version, it's hard for my eyes to find what work is actually being done
because there are so many braces and brackets and words. The big deal of
lambda syntax is that it lets you focus on the code that does the work (the
doStuff) instead of the adapter (the "new Runnable() { public void run()")
that the library needs around that code.

~~~
cbs
_it's hard for my eyes to find what work is actually being done_

Aside from if a lambda expression or anonymous class is the better choice
overall, this just happens to be a case that you're just not familiar with the
syntax. Its been years since I've done any work in java, but I read this over
some coffee and didn't even slow down for it.

Lambdas will be nice for the situations where there is more boilerplate than
implementation, but the anonymous inner class in java isn't going to die.

------
zokier
Any details on variable capturing from outer scope? The same as C# (apparently
capture all variables?)?

~~~
zbowling
yes, closures are implied. lambda's are almost useless without closures being
included.

~~~
artsrc
I think the difference between capturing values at call time and full closures
only matters if you are mutating variables, which my closures rarely do, since
my code is fairly functional'ish, so for me it does not matter.

------
mwsherman
OP mentions that there were other ideas in the running. Anyone know what they
were?

------
Rickasaurus
Groupthink: I think we should have a vote on if we're going to vote on when
we're going to set a deadline for deciding on lambda syntax.

