Java Has Always Had Closures

117 views
Skip to first unread message

clay

unread,
Sep 12, 2011, 3:32:12 PM9/12/11
to The Java Posse
On the recent episode of Java Posse, several people referred to Java's
lack of closures. This is wrong. Java has full closures and has always
had them.

A closure is when you define a function that "closes" over the local
environment from which the new function is defined and can access
local variables of that defining scope. Java absolutely does this.

I've recently done some programming with GWT (Java), JavaFX 2 (in
Java), and client-side JavaScript (not Java), and we've been using
closures quite extensively in all three.

Kevin Wright

unread,
Sep 12, 2011, 3:37:53 PM9/12/11
to java...@googlegroups.com
No... It hasn't

In order to have closures, you must first have functions (as per your definition).  Functions being first-class entities that can be freely passed around.

Java doesn't have functions, therefore it can't have closures.

It does have objects and methods though, so you can make a good approximation of a function by using a SAM (single abstract method) type.  You can even name the class "Function" if you so wish, but it's still an abstraction in the mind of the developer, it isn't a core construct in the language.




--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.




--
Kevin Wright
mail: kevin....@scalatechnology.com
gtalk / msn : kev.lee...@gmail.com
vibe / skype: kev.lee.wright
steam: kev_lee_wright

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra

clay

unread,
Sep 12, 2011, 3:48:09 PM9/12/11
to The Java Posse
Java has functions, it doesn't have "first class functions" where
functions are treated as objects.

That's not necessary for closures. A closure is when you define a
function that closes over the variable scope of the defining
environment. You can do that in Java with anonymous classes that wrap
defined functions.

Casper Bang

unread,
Sep 12, 2011, 3:48:14 PM9/12/11
to java...@googlegroups.com
Neal Gafter blogged about this way back in 2006:

Wow, 5 years and still no closures. No wonder he chose to move on!

Joseph Ottinger

unread,
Sep 12, 2011, 3:53:39 PM9/12/11
to java...@googlegroups.com
If Neal moved on because of closures... that's pretty lame indeed.

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To view this discussion on the web visit https://groups.google.com/d/msg/javaposse/-/AdDk0G2vp1UJ.

To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.



--
Joseph B. Ottinger
http://enigmastation.com

Ben Schulz

unread,
Sep 12, 2011, 3:55:54 PM9/12/11
to The Java Posse
On 12 Sep., 21:32, clay <claytonw...@gmail.com> wrote:
> A closure is when you define a function that "closes" over the local
> environment from which the new function is defined and can access
> local variables of that defining scope.
Not just local variables, anything denotable from the enclosing scope,
such as the method equals(Object), which happens to have a different
meaning inside the "closure" than outside. This is a contradiction of
your very definition ("a closure is a function which closes over the
[lexically enclosing] environment") and thus disproves your
hypothesis.
q.e.d.

With kind regards
Ben

Cédric Beust ♔

unread,
Sep 12, 2011, 4:05:20 PM9/12/11
to java...@googlegroups.com
Technically true but practically irrelevant.

Jave has indeed had closures since day one (e.g. Runnable, Callable, etc...). If you're not convinced, ask yourself the following question: is there any programming construct that you will be able to do in Java 8 with closure support that you can't do today with Runnable?

None.

The syntax will be nicer, but that's all Java 8 is adding in that area.

-- 
Cédric

mbien

unread,
Sep 12, 2011, 4:17:45 PM9/12/11
to The Java Posse
right, java 7 is already turing complete :)

Josh Berry

unread,
Sep 12, 2011, 4:30:30 PM9/12/11
to java...@googlegroups.com
On Mon, Sep 12, 2011 at 3:32 PM, clay <clayt...@gmail.com> wrote:
> A closure is when you define a function that "closes" over the local
> environment from which the new function is defined and can access
> local variables of that defining scope. Java absolutely does this.

The problem being that the local environment for the function you are
in in Java gets destroyed when you return from the function. The
compiler will copy over final values into the new environment that you
create with an anonymous class, but the environment that exists as you
create this instance gets destroyed. (Hence, requiring that any
variables exposed to the "closure" be final.)

That is, if we had true closure (even without first order functions),
you could declare two of them that communicated through a mutable
variable. Correct? (This is a legitimate question, not a rhetorical
trick.)

Josh Berry

unread,
Sep 12, 2011, 4:40:40 PM9/12/11
to java...@googlegroups.com
On Mon, Sep 12, 2011 at 3:32 PM, clay <clayt...@gmail.com> wrote:
> A closure is when you define a function that "closes" over the local
> environment from which the new function is defined and can access
> local variables of that defining scope. Java absolutely does this.

The problem being that the local environment for the function you are

clay

unread,
Sep 12, 2011, 4:54:22 PM9/12/11
to The Java Posse
The "final" keyword, means that the variable reference itself can't be
modified, but it doesn't impose or suggest any restrictions on the
contents of the variable.

You can absolutely mutate/change the contents of a final variable and
communicate state through that between different closures or different
parts of the application.

Tom Hawtin

unread,
Sep 12, 2011, 5:15:45 PM9/12/11
to The Java Posse
On Sep 12, 4:05 pm, Cédric Beust ♔ <ced...@beust.com> wrote:

> Jave has indeed had closures since day one (e.g. Runnable, Callable,
> etc...). If you're not convinced, ask yourself the following question: is
> there any programming construct that you will be able to do in Java 8 with
> closure support that you can't do today with Runnable?

Is this the point in the conversation where we hit Turing-
completeness?

> None.
>
> The syntax will be nicer, but that's all Java 8 is adding in that area.

Syntax is terser (nicer, I'm not so sure I'm willing to absolutely
commit to that) than 1.1, but there is also an alleged lighter
implementation available with method handles (alleged as the
optimisation may perhaps be harder and heavier).

Tom

Cédric Beust ♔

unread,
Sep 12, 2011, 5:35:13 PM9/12/11
to java...@googlegroups.com
On Mon, Sep 12, 2011 at 2:15 PM, Tom Hawtin <tack...@googlemail.com> wrote:
On Sep 12, 4:05 pm, Cédric Beust ♔ <ced...@beust.com> wrote:

> Jave has indeed had closures since day one (e.g. Runnable, Callable,
> etc...). If you're not convinced, ask yourself the following question: is
> there any programming construct that you will be able to do in Java 8 with
> closure support that you can't do today with Runnable?

Is this the point in the conversation where we hit Turing-
completeness?

No, that would be a cop out :-)

Java 8 will allow us to replace

foo(new Runnable() { public void run() { blah(); } })

with

foo( => blah())   (approximately)

These two constructs are extremely similar, and I think the former would definitely qualify as a closure to me, at least in spirit, if not literally.

-- 
Cédric


> None.
>
> The syntax will be nicer, but that's all Java 8 is adding in that area.

Syntax is terser (nicer, I'm not so sure I'm willing to absolutely
commit to that) than 1.1, but there is also an alleged lighter
implementation available with method handles (alleged as the
optimisation may perhaps be harder and heavier).

Tom
--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.

Josh Berry

unread,
Sep 12, 2011, 5:44:20 PM9/12/11
to java...@googlegroups.com
On Mon, Sep 12, 2011 at 4:54 PM, clay <clayt...@gmail.com> wrote:
> The "final" keyword, means that the variable reference itself can't be
> modified, but it doesn't impose or suggest any restrictions on the
> contents of the variable.
>
> You can absolutely mutate/change the contents of a final variable and
> communicate state through that between different closures or different
> parts of the application.

So, make a 2 closures and then alternate calling each where the first
increments an int, and the second prints it.

That is,

public void foo() {
int myInt = 0;
Runnable a = new Runnable() {
public void run() {
myInt++;
}
};
Runnable b = new Runnable() {
public void run() {
System.out.println(myInt);
}
};
a.run();
b.run();
}

If we had closures, you could do this, no? (Again, not being
rhetorical. This is just how I understand the situation.)

Serge Boulay

unread,
Sep 12, 2011, 6:17:34 PM9/12/11
to java...@googlegroups.com
most languages with closures allow this but not what is currently being proposed in Java 8. Closures in Java 8 currently do not permit capture of mutable local variables.
 
7.  Local variable capture
--------------------------

The current rules for capturing local variables of enclosing contexts
in inner classes are quite restrictive; only final variables may be
captured.  For lambda expressions (and for consistency, probably inner
class instances as well), we relax these rules to also allow for
capture of *effectively final* local variables.  (Informally, a local
variable is effectively final if making it final would not cause a
compilation failure.)

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.  Unless we are willing to
enforce (preferably statically) that such lambdas not escape their
capturing thread, such a feature may likely cause more trouble than it
solves.


 

Kevin Wright

unread,
Sep 12, 2011, 6:28:41 PM9/12/11
to java...@googlegroups.com
Of course, there's the old trick of making a "final" single element array, and passing that into your lambda expression/anonymous inner class/whatever.  The cell of that array can still happily be changed at a later point and the "closure" will see this mutated value when executed.

Get a few of these going without due diligence and, if you find race conditions funny, let the hilarity ensue!

And no, I'm not advocating that anybody does such a thing.

clay

unread,
Sep 12, 2011, 6:34:56 PM9/12/11
to The Java Posse
Easy:

public static void main(String[] args) {
final AtomicInteger myInt = new AtomicInteger(0);

Runnable a = new Runnable() {
@Override
public void run() {
myInt.incrementAndGet();
}
};
Runnable b = new Runnable() {
@Override
public void run() {
System.out.println(myInt.get());
}
};

a.run();
b.run();

opinali

unread,
Sep 12, 2011, 6:37:24 PM9/12/11
to java...@googlegroups.com
Josh beat me. In any formal definition of closure, it is clear and explicit that a closure fully captures the static environment. There's no restriction to mutation of bindings in the captured environment, not even in SICP where the language is Scheme and the authors have a strong bias towards functional purism even though they are not radical about it (but maybe because that was before developments like Haskell's monads).

Of course, it can be argued that capturing the full environment vs. capturing only the variables that the closed function actually needs, is implementation detail. This is true as long as the language does not support dynamic lookup of variables - Java doesn't, despite reflection; we can't inspect the frames of the call stack and look up local variables by name or by any other means. But the restriction of doing only by-value capture is not orthogonal with a language that allows destructive assignment (and for Java, "allows" is an understatement; that's its primary paradigm). Nobody in lambda-dev disputes this in the conceptual level; Oracle's only reasoning to not allow capture of mutable variables is the red herring of concurrency (i.e. closures will be very useful in concurrent/asynchronous frameworks and developers are too stupid to mix that with mutable capture, even with a modifier to make such captures explicit).

A+
Osvaldo

Josh Berry

unread,
Sep 12, 2011, 7:47:20 PM9/12/11
to java...@googlegroups.com
So, you are trolling? Java can accomplish what most people use
closures for no problem. I do not dispute this, but they are not
closures in the definition sense. This would be akin to claiming that
java always had varargs because you could have always just passed an
object array in at the end.

Alexey Zinger

unread,
Sep 12, 2011, 7:59:09 PM9/12/11
to java...@googlegroups.com
I don't wanna argue semantics.  That said, what we're getting in Java 8 isn't true closures.  The important distinction is that we don't get full execution flow control.  All we get is, as you said, syntactic niceties.  Now, the syntactic niceties are, of course, nice.  And I'm not a language zealot and therefore will not jump off a cliff because Java doesn't have "true" closures.  But in the real sense of the word, it doesn't.
 
Alexey



From: Cédric Beust ♔ <ced...@beust.com>
To: java...@googlegroups.com
Sent: Monday, September 12, 2011 4:05 PM
Subject: Re: [The Java Posse] Re: Java Has Always Had Closures

phil swenson

unread,
Sep 12, 2011, 9:47:35 PM9/12/11
to java...@googlegroups.com
http://en.wikipedia.org/wiki/Pedantic

Java doesn't have closures in the way most people think of closures.
It has closures in a half-assed, un-friendly way. So people don't use
them much and in effect, Java doesn't have closures.

Alexey Zinger

unread,
Sep 12, 2011, 10:27:12 PM9/12/11
to java...@googlegroups.com
Not sure who you're saying is a pedant in this conversation, but I would have to say that despite Java's closures not being really closures, people do use them quite a bit.  See the style of GWT API and Guava for a few good examples.
 
Alexey



From: phil swenson <phil.s...@gmail.com>
To: java...@googlegroups.com
Sent: Monday, September 12, 2011 9:47 PM

> For more options, visit this group at
> http://groups.google.com/group/javaposse?hl=en.
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "The Java Posse" group.
> To post to this group, send email to java...@googlegroups.com.
> To unsubscribe from this group, send email to

> For more options, visit this group at
> http://groups.google.com/group/javaposse?hl=en.
>

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+unsub...@googlegroups.com.

Josh Berry

unread,
Sep 12, 2011, 10:43:35 PM9/12/11
to java...@googlegroups.com
Yeah, I'll gladly confess that I think I'm being more pedantic in the
argument. Doesn't change my view of the subject and presentation as
trollish. Again, I need only point to the fact that you could do
"varargs" before they were added to java by just passing an
appropriate array. The literal syntax for that was actually less
intrusive than what is being pushed as closures in this thread.

And people use them quite a bit in more recent libraries because many
people are trying to pull over some really good ideas from other
places.

>> javaposse+...@googlegroups.com.


>> For more options, visit this group at
>> http://groups.google.com/group/javaposse?hl=en.
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "The Java Posse" group.
>> To post to this group, send email to java...@googlegroups.com.
>> To unsubscribe from this group, send email to

>> javaposse+...@googlegroups.com.


>> For more options, visit this group at
>> http://groups.google.com/group/javaposse?hl=en.
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "The Java Posse" group.
> To post to this group, send email to java...@googlegroups.com.
> To unsubscribe from this group, send email to

> javaposse+...@googlegroups.com.


> For more options, visit this group at
> http://groups.google.com/group/javaposse?hl=en.
>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "The Java Posse" group.
> To post to this group, send email to java...@googlegroups.com.
> To unsubscribe from this group, send email to

> javaposse+...@googlegroups.com.

clay

unread,
Sep 12, 2011, 11:16:59 PM9/12/11
to The Java Posse
People don't use closures in Java that much? I emphatically disagree.
I completed writing a JavaFX 2 application in Java: Every single
button handler or GUI event handler uses an anonymous class wrapped
around a function, and most of those access local or instance
variables from the defining scope, where my coworkers and I refer to
it as a closure. The Swing and GWT APIs are also designed for heavy
use of anonymous functions and closures (most Java server side web
frameworks don't use anonymous functions at all). We also do the same
thing in our (non Java) JavaScript client code and we call them
closures there as well.

No, I'm really not being pedantic. I use closures so extensively in
Java, it is ridiculous to say that they don't exist. That's like
telling me Java doesn't have a for loop or exceptions.

clay

unread,
Sep 12, 2011, 11:49:45 PM9/12/11
to The Java Posse
Osvaldo, are you saying that a pure closure implementation wouldn't
have the "final" variable restriction, but one could argue that that
is an implementation detail? If so, I'd completely agree that that is
an implementation detail.

One additional point:

The more academic functional programming purists who look down on Java/
C# and only program in Haskell tell me that Java has closures. Java
doesn't have first class functions (which people confuse with
closures), it has a clumsy syntax for functional programming, but it
does have the closure piece where you can define a function inside of
a function that can access the local variables of the outer function.

Cédric Beust ♔

unread,
Sep 13, 2011, 12:15:08 AM9/13/11
to java...@googlegroups.com
On Mon, Sep 12, 2011 at 7:27 PM, Alexey Zinger <inlin...@yahoo.com> wrote:
Not sure who you're saying is a pedant in this conversation, but I would have to say that despite Java's closures not being really closures, people do use them quite a bit.  See the style of GWT API and Guava for a few good examples.

And SWT, and Swing, or any graphical toolkit for that matter, and anything using java.concurrent.util, which probably includes every single Java web server in existence. To name a few.

-- 
Cédric

Kevin Wright

unread,
Sep 13, 2011, 2:27:12 AM9/13/11
to java...@googlegroups.com

This breaking news, just in: C has objects, and Lisp has static types.

More details to come as events unfold.

Message has been deleted

Roland Tepp

unread,
Sep 13, 2011, 2:49:36 AM9/13/11
to java...@googlegroups.com
There is an arguably nicer way to do this now that we have Generics:

http://luolong.blogspot.com/2010/06/delicious-wraps.html

Fabrizio Giudici

unread,
Sep 13, 2011, 3:51:44 AM9/13/11
to java...@googlegroups.com, clay
I won't dare to enter the ground of interpreting what's a closure
because I'd get it wrong. But I think that the following statements are
true:

1. "foobar" is a language construct that either is the same thing of a
closure or a subset of a closure
2. foobars are useful for programmers
3. the difference between a foobar and a closure, if any, is neglectable
from a practical point of view
4. Java has always had foobars, in form of SAM classes
5. Java 8 provides a nicer, shorter syntax for foobars

I think that points 1, 2, 4, and 5 are quite obvious and I suppose
nobody disagrees. So, the important point is #3. If you can't
demonstrate that point #3 is false, then clay and C�dric might be not
pedantic enough from a semantic point of view (not my business), but are
substantially right.

--
Fabrizio Giudici - Java Architect, Project Manager
Tidalwave s.a.s. - "We make Java work. Everywhere."
java.net/blog/fabriziogiudici - www.tidalwave.it/people
Fabrizio...@tidalwave.it

Russel Winder

unread,
Sep 13, 2011, 7:04:46 AM9/13/11
to java...@googlegroups.com
On Tue, 2011-09-13 at 07:27 +0100, Kevin Wright wrote:
>
[ . . . ]

> This breaking news, just in: C has objects, and Lisp has static types.
>
> More details to come as events unfold.
>
:-)

Kevin,

In reading the entries for this thread, I was at a loss as to where to
dive in. Thanks for providing a cue!


C++ prior to C++11 has what is effectively closures in that you can
create instances of classes with an operator ( ) overload and ensure
that the constructor requires parameters such that an instance of the
class has no free variables. This technique has now been folded into
the lambda functions introduced in C++11 and given a specialist syntax
so people don't have to roll their own.

Java not allowing operator overloading makes this just a tiny bit more
verbose: you have to call the function call or something. Nonetheless
the same programming idiom applies.

The issue here is the difference between "infrastructure that allows"
and "syntax that represents". Having "syntax that represents" is a
raising of the abstraction level that means (generally) that the
language is easier for programmers to write good programs. Clearly
there are counter-examples, but the point remains.

--
Russel.
=============================================================================
Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel...@ekiga.net
41 Buckmaster Road m: +44 7770 465 077 xmpp: rus...@russel.org.uk
London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder

signature.asc

Sam Reid

unread,
Sep 13, 2011, 10:50:15 AM9/13/11
to java...@googlegroups.com
The IntelliJ IDEA editor (9+) has a feature called "closure folding" for Java code that makes:

Runnable r = new Runnable() {
    public void run() {
        System.out.println( "Hello" );
    }
};

display and read like:

Runnable r = Runnable() { System.out.println( "Hello" ); };

With the "Runnable () {" and "}" grayed out to make it even easier to read.  Here's a link with more information and screenshots:

Furthermore, with autocomplete, all the user has to type to create this code block is Runnable r = new <autocomplete>System.out.println("hello");

So we can conclude a few things:
1. JetBrains considers Java to have closures
2. With appropriate tool support, Java closures can be easy to read and write

Sam

clay

unread,
Sep 13, 2011, 11:31:25 AM9/13/11
to The Java Posse
"This breaking news, just in: C has objects, and Lisp has static
types."

Rather than all the snarky replies, how about you actually explain
what makes the Closure-like functionality in Java not really true
closures?

I can articulate exactly why C doesn't have real objects. You can do
OO style programming in pure C, and you design your code as "objects"
in the conceptual sense, but you don't have language level support for
it.

People say "Java doesn't have closures" so frequently that people
believe it. But it is really just a common misuse of terminology. What
(I think) people mean, when they say that, is that Java doesn't have
first class functions (functions as objects) and a concise anonymous
functions syntax. But, closures is a feature that Java has always had.
I'm not trolling, I'm just trying to get the labels and terminology
accurate and clear.

Josh Berry

unread,
Sep 13, 2011, 12:04:54 PM9/13/11
to java...@googlegroups.com
On Tue, Sep 13, 2011 at 11:31 AM, clay <clayt...@gmail.com> wrote:
> "This breaking news, just in: C has objects, and Lisp has static
> types."
>
> Rather than all the snarky replies, how about you actually explain
> what makes the Closure-like functionality in Java not really true
> closures?

I already did. Here, spot the closure in Scala:

def printNumbers(max:Int) {
for( x<- 1 to max) {
println(x)
}
}

It isn't enough that the closure could get a copy of x from the
environment, it has to capture mutations to it, as well. Can you
accomplish the same thing with other means? Of course. (And,
someone please correct me if I am wrong on this.)

> I can articulate exactly why C doesn't have real objects. You can do
> OO style programming in pure C, and you design your code as "objects"
> in the conceptual sense, but you don't have language level support for
> it.

I articulated exactly what would be necessary for Java to have
closures. That you think it counts to modify the program to use
different objects shows that you aren't actually getting the argument.
This would be like saying Java has "pass by reference" because I can
do the following:

public void swap(Foo a1, Foo a2) {
Foo tmp = new Foo(a1);
a1.setValuesFrom(a2);
a2.setValuesFrom(tmp);
}

Sure, you can "swap" elements in this way. But this is not what pass
by reference means.

I'm sympathetic to both arguments. Hell, I incorrectly call java pass
by reference all the time. I get called on it and sometimes I try and
backpedal what I meant and claim I was correct. The fact is that it
is not pass by reference, no matter how well I know what I meant to
say, to claim otherwise is wrong.


And this is ignoring the fact that anonymous inner classes have not
been there since day 1.

Ben Smith-Mannschott

unread,
Sep 13, 2011, 12:15:25 PM9/13/11
to java...@googlegroups.com
On Tue, Sep 13, 2011 at 17:31, clay <clayt...@gmail.com> wrote:
> "This breaking news, just in: C has objects, and Lisp has static
> types."
>
> Rather than all the snarky replies, how about you actually explain
> what makes the Closure-like functionality in Java not really true
> closures?

I'm not the O.P, but I'll take a swing:

"Full" Closures capture the lexically scoped *variables* at the time
of closure creation. Changes the closure later makes to those
variables when it is run will be visible to any other closure that has
captured those same variables. (Let's call this "communication by
mutation".)

Java's anonymous inner classes copy the *values* bound to lexically
scoped variables at the time of object instantiation. You can achieve
up "communication by mutation" by an additional level of indirection:
just let your variable hold a reference to something that is mutable.

In languages where variables are immutable, such as Clojure, this is a
distinction without a difference.

The fact that Java's AIC only copy values and don't capture variables
is something I don't lose sleep over since I try to avoide mutability
where I can.

// ben

clay

unread,
Sep 13, 2011, 12:49:55 PM9/13/11
to The Java Posse
Ben + Josh, is this an accurate summary of your viewpoints: Java
doesn't have true closures because of the "final" variable requirement
and that any mutability of "closed" variables from the outer
environment requires a level of indirection.

That's a logically consistent argument, although it's real language
lawyer, splitting hairs argument.

I'd still say that the language level limitations that are holding
Java back from a more functional programming style isn't the "final"
variable restriction of Closure like functionality, but the lack of
first class functions and a more concise anonymous function syntax.
And, ideally, Java would have a standard collections library with
persistent immutability support (like Scala's collections).

Josh Berry

unread,
Sep 13, 2011, 1:28:14 PM9/13/11
to java...@googlegroups.com
On Tue, Sep 13, 2011 at 12:49 PM, clay <clayt...@gmail.com> wrote:
> Ben + Josh, is this an accurate summary of your viewpoints: Java
> doesn't have true closures because of the "final" variable requirement
> and that any mutability of "closed" variables from the outer
> environment requires a level of indirection.
>
> That's a logically consistent argument, although it's real language
> lawyer, splitting hairs argument.

I offered that I am the one being pedantic. :) How do you feel about
whether or not java has "pass by reference?" For those that care that
objects are not copied to the stack, the fact that you can not write a
swap is likely a splitting hairs argument, as well. (For those that
care about the swap, it is key.)

And, yes, I have had several times when I would have liked to do something like:

for (int x = 0; x < count; x++ ) {
new Runnable() { public void run() {someFunctionOn(x);}}.run();
}

This would require a closure. A function literal would help, but a
closure is necessary to make it work.


> I'd still say that the language level limitations that are holding
> Java back from a more functional programming style isn't the "final"
> variable restriction of Closure like functionality, but the lack of
> first class functions and a more concise anonymous function syntax.
> And, ideally, Java would have a standard collections library with
> persistent immutability support (like Scala's collections).
>

I don't disagree. What you are describing, though, sounds like you
really should jump ship to one of the alternative languages. Not
because java sucks, but because other languages have what you want.

clay

unread,
Sep 13, 2011, 2:15:46 PM9/13/11
to The Java Posse
Regarding "pass by reference", most people will say Java passes
objects by reference, when it is more accurate to say that they pass
object references by value. I don't think there is much confusion or
debate on that issue.

With Closures, there is a lot of confusion. Java has something
extremely close to closures, and only a real pedant can debate the
distinction. I also think when people say that Java lacks closures,
they are referring to first class functions and concise anonymous
function syntax instead.

"What you are describing, though, sounds like you really should jump
ship to one of the alternative languages."

That's actually a different issue: which language is a better fit for
a project. And I don't disagree, for functional programming support,
clearly Java is behind the pack. For this thread, I just wanted to
clarify what a closure is, and what people really mean when they say
that is missing from Java.

For your loop example, can't you simply do:

for (int x = 0; x < count; x++ ) {
final int x2 = x;
new Runnable() { public void run() {someFunctionOn(x2);}}.run();
}

or

for (int x = 0; x < count; x++ ) {
someFunctionOn(x);
}

Josh Berry

unread,
Sep 13, 2011, 2:54:07 PM9/13/11
to java...@googlegroups.com
On Tue, Sep 13, 2011 at 2:15 PM, clay <clayt...@gmail.com> wrote:
> Regarding "pass by reference", most people will say Java passes
> objects by reference, when it is more accurate to say that they pass
> object references by value. I don't think there is much confusion or
> debate on that issue.

I think you'd be surprised by how often there is confusion over this
very point. :) (Granted, I think some of the escape analysis tricks
whereby scaler replacement happens just throws a giant wrench at this
one. I may be horribly abusing these terms.)

> With Closures, there is a lot of confusion. Java has something
> extremely close to closures, and only a real pedant can debate the
> distinction. I also think when people say that Java lacks closures,
> they are referring to first class functions and concise anonymous
> function syntax instead.

I don't disagree that most people are more concerned with function
literals than they are closures. Doesn't change the fact that Java
doesn't have closures.

> For your loop example, can't you simply do:

There are many different ways I could have done that differently. I
wasn't off to produce a program that you could not do in Java. I
simply was showing what Java could do if it had closures. Much like I
can quite confidently say you can not write the following java
program:

public void addSomeMatrix(Matrix a, Matrix b) {
return a + b;
}

Of course you can represent the same thing with a.plus(b) most likely.
This gets ugly as sin if you are trying to move an algorithm into
java but want to use BigDecimal, for example.

Kevin Wright

unread,
Sep 13, 2011, 3:29:16 PM9/13/11
to java...@googlegroups.com
On 13 September 2011 16:31, clay <clayt...@gmail.com> wrote:
"This breaking news, just in: C has objects, and Lisp has static
types."

Rather than all the snarky replies, how about you actually explain
what makes the Closure-like functionality in Java not really true
closures?

I can articulate exactly why C doesn't have real objects. You can do
OO style programming in pure C, and you design your code as "objects"
in the conceptual sense, but you don't have language level support for
it.


Quite!

You can do functional style programming in pure Java, and you design your code as "functions" in the conceptual sense, but you don't have language level support for it.
 
People say "Java doesn't have closures" so frequently that people
believe it. But it is really just a common misuse of terminology. What
(I think) people mean, when they say that, is that Java doesn't have
first class functions (functions as objects) and a concise anonymous
functions syntax. But, closures is a feature that Java has always had.
I'm not trolling, I'm just trying to get the labels and terminology
accurate and clear.



If "Java has closures" is discussed in terms of what is possible, regardless of of the need to use lots of boilerplate or an awkward encoding for "Favourite paradigm #3(tm)", then we may as well extrapolate to the logical conclusion that every language has every feature so long as it's Turing complete.

Ultimately, *anything* is possible in a turing-complete language, even BrainF**k, so long as you're willing to jump through enough hoops.  This is not the generally accepted meaning when someone states that language X "has" feature Y, or else we'd all be running around claiming that every language has every feature and we'd have a very difficult time talking about disambiguating features on this very mailing list.

The usual understanding of the phrase "lang X has Y" is that "language X has semantic constructs in support of feature Y".  Closures are defined in terms of functions, and Java most certainly does NOT have semantic support for functions as a first class construct (and no, methods are not the same thing). Ergo, Java does not have closures.

Fabrizio Giudici

unread,
Sep 13, 2011, 2:32:14 PM9/13/11
to java...@googlegroups.com, Josh Berry
On 09/13/2011 07:28 PM, Josh Berry wrote:
> On Tue, Sep 13, 2011 at 12:49 PM, clay<clayt...@gmail.com> wrote:
>> Ben + Josh, is this an accurate summary of your viewpoints: Java
>> doesn't have true closures because of the "final" variable requirement
>> and that any mutability of "closed" variables from the outer
>> environment requires a level of indirection.
>>
>> That's a logically consistent argument, although it's real language
>> lawyer, splitting hairs argument.
> I offered that I am the one being pedantic. :) How do you feel about
> whether or not java has "pass by reference?" For those that care that
> objects are not copied to the stack, the fact that you can not write a
> swap is likely a splitting hairs argument, as well. (For those that
> care about the swap, it is key.)
>
> And, yes, I have had several times when I would have liked to do something like:
>
> for (int x = 0; x< count; x++ ) {
> new Runnable() { public void run() {someFunctionOn(x);}}.run();
> }
>
> This would require a closure. A function literal would help, but a
> closure is necessary to make it work.
This works indeed and no closure required:

for (final AtomicInteger x = new AtomicInteger(0) ;
x.intValue() < 10; x.incrementAndGet())
{


new Runnable()
{
@Override
public void run()
{

System.err.println(x.intValue());
}
}.run();
}

--
Fabrizio Giudici - Java Architect, Project Manager
Tidalwave s.a.s. - "We make Java work. Everywhere."

fabrizio...@tidalwave.it
http://tidalwave.it - http://fabriziogiudici.it

Ricky Clarkson

unread,
Sep 13, 2011, 6:02:08 PM9/13/11
to java...@googlegroups.com
It's myth-debunking time.  It's been so long since I had a good myth-debunk.

You can't spot the closure in that Scala code because closures are not syntax.  They are an implementation mechanism provided by compilers.  The term we should have been using all these years is lambdas, which is what Haskell, Lisp and C# call it.  And that's what Java doesn't have; a syntax for lambdas.  It instead has a syntax for anonymous classes, which can be used to emulate lambdas, and pretty well.

So, let's talk about how to spot closures.  You can spot them in javac by the fact the anonymous classes cause Foo$1 etc. classes to be generated.  And if you look closely you'll see that all local variables used by the anonymous class are copied to the anonymous class, as if it were not an anonymous class at all, but a class named 1 with some constructor parameters that it copies to fields.

That implementation technique simply wouldn't work for mutable values; you'd have more than one version of the value depending on whether you read it from within the anonymous class or from outside it.  Does that mean Java has no closures?  Well, only if Erlang and Haskell also have no closures (hint: they have closures), as those languages only have immutable variables.

Java does have closures, but they are limited.  To say Java doesn't have closures based on this limitation is, well, irritating.

Is this worse than having unlimited closures?  Let's look at this example from the C# language specification (don't worry if you don't know C#, it's basically Java 8, right?):

The example

using System;

delegate void D();

class Test
{
   static D[] F() {
      D[] result = new D[3];
      for (int i = 0; i < 3; i++) {
         int x = i * 2 + 1;
         result[i] = () => { Console.WriteLine(x); };
      }
      return result;
   }

   static void Main() {
      foreach (D d in F()) d();
   }
}

produces the output:

1
3
5

However, when the declaration of x is moved outside the loop:

static D[] F() {
   D[] result = new D[3];
   int x;
   for (int i = 0; i < 3; i++) {
      x = i * 2 + 1;
      result[i] = () => { Console.WriteLine(x); };
   }
   return result;
}

the output is:

5
5
5

I'll let you ponder the implications of that.  Personally I favour removing mutability where possible, so I'm fine with Java's limitation apart from on those occasions where it annoys the hell out of me (using APIs that take Runnables, for example, so there's no way of passing a result back to the surrounding code).  I'd argue it's better to have more verbose code in a minority of cases than potential bugs in the majority.

Regarding IDEA's code folding, I use and love it, but we all know that the sad old grey corporate standard is Eclipse (the splash screen should be an animation of a boot stamping on a human face forever), and if the code looks ugly in Eclipse it isn't going to fly very far.  It can't even be in a plugin because a) is the plugin approved software? b) Johnny installed a plugin last year and had to reinstall Eclipse because some odd obscure interaction between maven, Eclipse, Subversion and authenticated proxies suddenly stopped working.

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.

opinali

unread,
Sep 13, 2011, 7:06:19 PM9/13/11
to java...@googlegroups.com
JavaFX2 and GWT are exceptions to the rule, the vast majority of Java APIs/frameworks are not designed to benefit from intense use "closures" even in cases where such intense use would usually be a no-brainer design - remarkably collections (where are methods like collect, select, foreach etc.) - this alone is enough evidence that Java does not have decent closure support.

Notice that both JavaFX2 and some other very recent APIs (e.g. for concurrency) were/are being explicitly designed with Java 8's lambdas in mind. The master plan is that right now we need that horrendous code with inner classes, but RSN we'll be using the same frameworks with lambdas and THEN these frameworks will be used they way they were designed to be used. (But that way will not yet be as powerful as in languages with full closures.)

Finally, let's propose a pact, shall we?

1) Everybody agrees that (a) inner classes are functionally equivalent to Java 8's lambdas, and (b) both are compatible with a "pragmatic" definition of closures;
2) Everybody agrees that this form of closures that we have above, has the defect of not being orthogonal with the rest of the language. Mutability is an extremely fundamental aspect of Java; I too, like to write side-effect free code in Java (see my article in NetBeans Magazine Issue 1...), but this is a programmer idiom that has zero support from the language. And we cannot claim Java to be some sort of functional-hybrid language or to contain a functional subset; the closure-specific restriction to mutable capture is pathetically too-little to qualify for that.

A+
Osvaldo


On Monday, September 12, 2011 11:16:59 PM UTC-4, clay wrote:
People don't use closures in Java that much? I emphatically disagree.
I completed writing a JavaFX 2 application in Java: Every single
button handler or GUI event handler uses an anonymous class wrapped
around a function, and most of those access local or instance
variables from the defining scope, where my coworkers and I refer to
it as a closure. The Swing and GWT APIs are also designed for heavy
use of anonymous functions and closures (most Java server side web
frameworks don't use anonymous functions at all). We also do the same
thing in our (non Java) JavaScript client code and we call them
closures there as well.

No, I'm really not being pedantic. I use closures so extensively in
Java, it is ridiculous to say that they don't exist. That's like
telling me Java doesn't have a for loop or exceptions.

Josh Berry

unread,
Sep 13, 2011, 7:47:10 PM9/13/11
to java...@googlegroups.com
On Tue, Sep 13, 2011 at 6:02 PM, Ricky Clarkson
<ricky.c...@gmail.com> wrote:
> It's myth-debunking time.  It's been so long since I had a good myth-debunk.

I'm not sure what myth I was using that you debunked. :( The example
I gave is a full closure where one wouldn't even realize a "lambda"
was being used in most cases. In fact, I'm not sure how you would
provide a full function to a for comprehension that referenced
variables without a full closure.

> You can't spot the closure in that Scala code because closures are not
> syntax.  They are an implementation mechanism provided by compilers.  The
> term we should have been using all these years is lambdas, which is what
> Haskell, Lisp and C# call it.  And that's what Java doesn't have; a syntax
> for lambdas.  It instead has a syntax for anonymous classes, which can be
> used to emulate lambdas, and pretty well.

I have agreed there is a difference between function literals
(lambdas) and what a closure is. I have even ceded that I am being
pedantic.

The rest of your post seems to just be saying "if we change the
definition of closure, then Java has them."

clay

unread,
Sep 13, 2011, 7:58:02 PM9/13/11
to The Java Posse
From the best I can gather, the principle disagreement is definitions.
There are three views in this thread:

A) Java has closures. Closures, by definition, do not necessarily
require lambdas or first class functions, which Java doesn't have.
B) Closures, by definition require lambdas and/or first class
functions, so since Java doesn't have those, it can't have closures.
C) Pure closures, by definition, don't limit you to accessing only
"final" variables, so the anonymous class functionality doesn't
qualify as a closure.

Osvaldo,

Regarding point #1: First, I think you mean anonymous classes, not
inner classes. Secondly, I'd stress that anonymous functions (lambdas)
are a distinct feature from closures. A language can have one feature
but not the other. Java has closures, but not lambdas. And I can't
think of them off the top of my head, but I'm sure there are languages
with lambdas that don't close over the defining environment, and
therefore don't have closures.

Regarding point #2: I'm not sure what you are getting at here. Sure,
Java is behind the pack in terms of immutable programming and
functional programming support, but you can use third party libraries
like Functional Java and adopt that style as a programmer. Only a few
languages like Haskell really force those concepts on you and
guarantee safety from mutability issues. In Scala, immutable code and
functional programming still requires programmer compliance and it's
easy to write imperative mutable code. Regardless, this seems like a
tangential issue.

Kevin,

I'm not arguing that Java has closures because you can achieve the
same goals without real language level support. I'm arguing that
closures are inner functions/methods that can access variables from
the outer function/method scope, and the Java language syntax
completely supports that. You are claiming that closures require
lambdas by definition, and I disagree with you on that definition.
Java doesn't have lambdas. Sure, you can achieve similar results with
anonymous classes, but the Java language itself doesn't provide
lambdas.

Josh Berry

unread,
Sep 13, 2011, 8:18:05 PM9/13/11
to java...@googlegroups.com
My only problem with this, is to my knowledge we have invented the
"pure closure" terminology. Again, this would be akin to my claiming
that Java has had varargs since day one. You could always pass object
arrays, after all. Nobody, to my knowledge, ever claimed those were
the same thing. (I'm sure someone out there did.)

That is, you seem to be claiming that java 1.3 had varargs because you
could have written the method:

String.format("%s", new Object[] { someObject });

This is just a minor inconvenience over the new syntax that allows
varargs, but that small change means everything. Same goes for
function literals. I confess that I can not think of too many places
where I would miss full closures. About the best I can think is in a
for comprehension style thing, where you can drop the necessity for
determining all of the arguments that the inner "lambda" needs, as it
can just capture the surrounding variables. And, as pointed out, you
could just move the indirection to the object being held. (Not sure
this really looks any better at all.)

Alexey Zinger

unread,
Sep 14, 2011, 3:10:32 AM9/14/11
to java...@googlegroups.com
Folks, I mentioned this earlier, but no one seemed to pick up on it.  The one real difference between closures and constructs like Java's SAM's or anonymous functions is how control flow is treated.  Not just in trivial cases like branching and looping, but think about continuations, exception propagation, etc.  This is where Java comes up short if you wanna do those things.  My understanding is that Java 8 syntax doesn't address this, so we're still stuck using whatever we had before, but with cleaner, nicer presentation (syntax).  Again, not something I consider a deal breaker, but an important factor nonetheless.
 
Alexey



From: clay <clayt...@gmail.com>
To: The Java Posse <java...@googlegroups.com>
Sent: Tuesday, September 13, 2011 2:15 PM
Subject: [The Java Posse] Re: Java Has Always Had Closures

Ben Smith-Mannschott

unread,
Sep 14, 2011, 6:20:21 AM9/14/11
to java...@googlegroups.com
Yea, Java 8 brings nicer syntax for Java's
value-copying-closures-which-are-really-instances-of-anonymous-inner-classes.
Java 8 won't bring any kind of continuation support.

Continuations are a powerful concept. Scheme demonstrates that they
can be powerfully combined with closures. But, it seems to me that
closures and continuations are separable concepts. I don't think
mixing the two concepts helps to clarify things.

That said, the earlier BBGA closure proposal touched on three points:

(1) closures
(2) function types
(3) control abstraction similar to what's shown by the examples in the
linked article (implying a limited kind of continuation support under
the covers.)

What's planned for JDK8 is only #1, where SAM plays the role of #2,
though they say they are leaving the door open for introducing #2 at
some point in the future.

// Ben

> javaposse+...@googlegroups.com.


> For more options, visit this group at
> http://groups.google.com/group/javaposse?hl=en.
>
>
>

> --
> You received this message because you are subscribed to the Google Groups
> "The Java Posse" group.
> To post to this group, send email to java...@googlegroups.com.
> To unsubscribe from this group, send email to

> javaposse+...@googlegroups.com.

clay

unread,
Sep 14, 2011, 10:19:23 AM9/14/11
to The Java Posse
That's a completely vague explanation. Which specific control flow
behavior is required for full closure functionality? What about
exception propagation isn't being done correctly? I've never heard
this point before. I thought closures were specifically about
"closing" over the environment of the outer function.

Would you consider JavaScript to have the correct control flow/
exception propagation behavior to qualify as supporting full closures?
How about Scala, Clojure, Haskell, C#, and the old FX Script?

Alessio Stalla

unread,
Sep 14, 2011, 4:49:47 PM9/14/11
to The Java Posse


On 13 Set, 09:51, Fabrizio Giudici <fabrizio.giud...@tidalwave.it>
wrote:
> I won't dare to enter the ground of interpreting what's a closure
> because I'd get it wrong. But I think that the following statements are
> true:
>
> 1. "foobar" is a language construct that either is the same thing of a
> closure or a subset of a closure
> 2. foobars are useful for programmers
> 3. the difference between a foobar and a closure, if any, is neglectable
> from a practical point of view
> 4. Java has always had foobars, in form of SAM classes
> 5. Java 8 provides a nicer, shorter syntax for foobars
>
> I think that points 1, 2, 4, and 5 are quite obvious and I suppose
> nobody disagrees. So, the important point is #3. If you can't
> demonstrate that point #3 is false, then clay and C dric might be not
> pedantic enough from a semantic point of view (not my business), but are
> substantially right.

Well, a practical point of view depends on what, in practice, you want
to achieve ;)

I think that for the typical usage of inner classes in Java, there's
no practical difference. Still, as soon as you step out of typical use
patterns, you can be bitten if you don't know the rules.

In detail, a closure is a function that captures the entire lexical
environment it's defined in. If we gloss over the fact that Java has
no functions, and we treat instance methods as if they were functions
[*], we still have that Java methods are not closures because they
capture only a part of their surrounding lexical environment, that is,
final local variables. Note that:

- whether loop variables are implemented with one binding per
iteration vs one binding per loop + assignment (the capture in the for
loop example presented upthread) is orthogonal to closures.

- whether the language supports anonymous functions (lambdas) is
orthogonal as well.

- mutability of captured variables is not a requirement for closures
in general, but it is *in languages that have mutable variables* like
Java, because the captured environment inside the closure must be
indistinguishable from the one outside.

- mutable captured locals are a key feature to implement lightweight
prototype-based object systems in non-OO languages (such as Scheme and
Lisps before Common Lisp) but that's irrelevant in Java.

- mutable captured locals (in languages with mutable local variables)
are a key feature to implement closure-based control abstractions.
This is not that irrelevant in Java. Still, control abstractions need
to capture more than just variables, see below.

- lexical environment is not just local variables, it's everything
reachable lexically, such as labels and surrounding loops (for break
and continue). The return statement is peculiar because it can be
argued that it must refer to the lexically enclosing method or to the
lambda itself, and both have pros and cons. In Lisp return refers to
the lexically enclosing block, but in Lisp return is not typically
used to return a value from a function (the value of the last
expression is automatically returned), so this is not a concern in
practice. In Java it's much more debatable. Exception handlers,
instead, are dynamically bound, so they are out of the question.

To summarize: for the average developer, anonymous inner classes in
Java are closures. He will sometimes be bitten by them not capturing
something he thought they would, but that's hardly a problem,
especially with modern IDEs. With respect to the advancement of the
language, and for framework writers, anonymous inner classes are not
really closures, but in practice that's a minor nuisance. Java has far
worse problems than lack of closures.

Peace,
Alessio

[*] generally they're not, because they're not first-class, but in the
special case of SAM types, it's indeed possible to use the SAM
instance as a method reference.

opinali

unread,
Sep 14, 2011, 8:38:22 PM9/14/11
to java...@googlegroups.com
Hi clay,

Ok let's be more formal now. I agree with option A below (instead of B); "closure" is very well defined in numerous classic CS books as the pairing between a function and an environment that provides bindings to its free variables. The concept comes from lambda calculus where functions can only exist in the form of functions, so I understand view B - but practical programming languages are very distant from pure lambda calculus; only in the Lisp family (I think) they are really the same because functions are just sugar for a lambda - i.e. a function is a lambda that is bound by some name to some environment. But there are many other languages, including Java, where this doesn't happen, unless you interpret the concept of "environment" as something more general, including the all scoping rules, classloaders, etc. IMHO this is going a bit too far, I'm happy with a definition of closures that does not depend from lambdas.

Now back to my points 1/2, let's try to refine the discussion to its true essentials: the major point of debate is whether Java's closures (with or without Java 8's lambdas) are "good enough". So let's try to define what constitutes good enough. I am a strong advocate of very powerful closures; I was rooting for BGGA with its non-local returns, control abstractions..., but I concede that these features are only necessary to extend Java's paradigm, allowing significant new idioms. But it's fair to require for "good enough", an implementation of closures that is at least sufficient to get along with the *existing* language paradigm, idioms and other features (typesystem, OO model etc.) - anything better that that is a bonus. If we agree on this, then "good enough" boils down to orthogonality. And the current support for closures (without capture of mutable variables) is clearly NOT orthogonal, because destructive assignment is a HUGE part of the Java language. No amount of fancy functional-esque frameworks or conventions can change this simple fact. It's broken since JDK 1.1's introduction of inner classes, and it will be broken in Java 8's even with lambdas, nice syntax, and tons of new or retrofitted APIs to use closures/lambdas.

A+
Osvaldo

Alexey Zinger

unread,
Sep 14, 2011, 9:00:19 PM9/14/11
to java...@googlegroups.com
Not sure what's vague about it.  I can only refer you once again to the link I originally posted for a full explanation of this.  As to whether other languages you mention satisfy this requirement, to be honest, I'm not 100% certain because I'm not familiar enough with said languages.  I can say the following:

C# certainly has non-local returns in the form of yields.
Scala apparently has some continuation support in the form of a library in 2.8 -- my grasp on this is very shaky.

But the end result is not whether language X or Y supports or doesn't support closures.  The important debate I think is whether what Java has (whether we choose to call it closures or not) is generally sufficient.  I say yes.  My biggest gripe is not so much with non-local returns, but with exception propagation.  Some baby steps were taken toward that goes in java.util.concurrent, but it's quite limited and its abstractions leak badly into Java's type and exception systems.  But it's a hard problem anyway you cut it and I'm not overly upset.  It is what it is.  Know it and work with it, I say it.
 
Alexey



From: clay <clayt...@gmail.com>
To: The Java Posse <java...@googlegroups.com>
Sent: Wednesday, September 14, 2011 10:19 AM

Subject: [The Java Posse] Re: Java Has Always Had Closures

Ricky Clarkson

unread,
Sep 14, 2011, 9:15:30 PM9/14/11
to java...@googlegroups.com
I think the problem is that whenever you start trying to make sure that all code wrapped in a lambda behaves the same as code not wrapped in a lambda (return, break, this, continue, throw all behaving the same way) you get into odd territory and someone picks up on it and reacts.

Scala actually does some* of what Gafter's original proposal did regarding control, and the reality is I've only ever noticed when I explicitly tested it to see if I could observe a NonLocalReturnException.  However, I don't think we're going to win that fight, and C#'s level of lambda support really is a marked improvement over what we have in Java today.

* some, because Scala doesn't have continue or break.

--
Skype: ricky_clarkson


--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To view this discussion on the web visit https://groups.google.com/d/msg/javaposse/-/53VocU4KYT0J.

To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.

opinali

unread,
Sep 14, 2011, 11:12:24 PM9/14/11
to java...@googlegroups.com
On Wednesday, September 14, 2011 9:15:30 PM UTC-4, Ricky Clarkson wrote:
I think the problem is that whenever you start trying to make sure that all code wrapped in a lambda behaves the same as code not wrapped in a lambda (return, break, this, continue, throw all behaving the same way) you get into odd territory and someone picks up on it and reacts.

This seems to be mixing things. Code inside an inner class certainly behaves exactly like all other code; specifically, you can define mutable variables and you can assign to these variables. So the typesystem inside the "closure" is exactly the same. Which in this case, makes inner classes even more broken, it would be cleaner if inner classes had been designed as a pure-functional subset of the language that couldn't do destructive assignments at all.

See Guy Steele's comments about inner classes: http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg04044.html - Java was initially planned to have closures, including mutable capture, but that was cut from JDK 1.0 and when they introduced inner classes in 1.1, it didn't have mutable capture and the reason was just "users feared the performance cost" - maybe reasonable concern with JDK 1.0's VM with the crappiest GC ever, but an obsolete issue since HotSpot, not to mention that other language features already ignore any concerns (performance or other) of implicit allocations, like Steele points. Also, James Gosling referred to inner classes as an "uncomfortable compromise ... that didn't really solve any problems": http://blogs.oracle.com/jag/entry/closures. And a third "father of Java", Bill Joy, also wanted full support for closures since day one: http://www.blinkenlights.com/classiccmp/javaorigin.html

TL;DR: The mutable capture limitation of inner classes was NOT introduced by design. Not one of the original Java designers are proud of inner classes. Any attempt to justify this limitation as something that makes sense with good language design principles, is rewriting history - "it's not a bug, it's a feature".

A+
Osvaldo

Ricky Clarkson

unread,
Sep 15, 2011, 3:10:39 AM9/15/11
to java...@googlegroups.com
What I perhaps didn't make clear is that I'm talking about taking some code that's part of a method, and then making it part of a lambda within that method.

E.g., in some imaginary syntax:

void foo() {
  if (Math.random() < 0.5)
    return;
  System.out.println("Foo");
}

void foo() {
  timeHowLongThisTakes( () => {
    if (Math.random() < 0.5)
      return;
  } );
  System.out.println("Foo");
}

Return is one example; others are break, continue and throw.  The meaning is not kept if you wrap that code into a new Runnable() { public void run()... }

Gafter's original, well thought-out, argument was that wrapping code in a closure should not affect its meaning, which makes a lot of sense, but the actual mechanisms needed to do that at least before engaging the VM team are odd, it used exceptions under the hood to manage these things, and there were objections to that.  And (answered) questions about what return; would mean if the lambda were to be executed on a different thread to the surrounding method.

I think at this stage it makes sense to stick with a restricted lambda and get that in stone.  The current proposal does not in any way preclude Oracle from adding support for capturing mutable variables, a notation for outer returns, enabling break and continue, and making throws able to be transparent.

Regarding mutable variables, I'm sure you read the passage I quoted from the C# specification and can appreciate that it's not all roses without that limitation.  It's not just theoretical, in my brief time on Freenode's ##csharp I noticed it appeared fairly often.  Whether it was deliberate 14 years ago I don't think matters any longer.
--
Skype: ricky_clarkson


To view this discussion on the web visit https://groups.google.com/d/msg/javaposse/-/Fff1UZB3f5EJ.

opinali

unread,
Sep 15, 2011, 9:37:02 AM9/15/11
to java...@googlegroups.com
Oh got it. I agree that return/break/continue (the so-called non-local returns) are a problem, although they are only such a big problem if we don't want to improve the classfile/bytecode/VM specs to have a specialized mechanism for this in order to not depend on the exception hack. Unfortunately, too many Java language improvements are tainted by this criteria of desiring as few changes to the VM platform as possible.

But I don't see this problem as a justification for the separate issue of mutable capture. We're talking about completely distinct features. Capturing mutable local vars has a trivial implementation (lifting the variable to a field of the closure object, visible both from the defining scope and from the closure code).

I read the C# example, and it didn't impress me; it's not just contrived, it's a VERY contrived example. You can easily build such examples to show that every single feature of any language can be involved in some incorrect/confusing code. In the example, the bug is not caused only by mutable capture - it's mostly likely caused by programmer's failure to realize that the execution of the closure will be deferred. This is the most fundamental property of a closure if compared to a regular block or expression inside the containing method; developers can shoot themselves in the foot all day long if they fail to be aware of when the code of closures is actually executed, without even needing mutable capture. Taking a page from lambda-dev (from Neal Gafter IIRC), closures (including mutable capture) are an ages-old feature which use is time-proven by numerous languages.

A+
Osvaldo
--
Skype: ricky_clarkson


--
Skype: ricky_clarkson



To post to this group, send email to jav...@googlegroups.com.
To unsubscribe from this group, send email to javapo...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.

Josh Berry

unread,
Sep 15, 2011, 11:17:43 AM9/15/11
to java...@googlegroups.com
On Thu, Sep 15, 2011 at 9:37 AM, opinali <opi...@gmail.com> wrote:
> I read the C# example, and it didn't impress me; it's not just contrived,
> it's a VERY contrived example. You can easily build such examples to show
> that every single feature of any language can be involved in some
> incorrect/confusing code. In the example, the bug is not caused only by
> mutable capture - it's mostly likely caused by programmer's failure to
> realize that the execution of the closure will be deferred. This is the most
> fundamental property of a closure if compared to a regular block or
> expression inside the containing method; developers can shoot themselves in
> the foot all day long if they fail to be aware of when the code of closures
> is actually executed, without even needing mutable capture. Taking a page
> from lambda-dev (from Neal Gafter IIRC), closures (including mutable
> capture) are an ages-old feature which use is time-proven by numerous
> languages.

Just lifting the variable to a field means you have completely moved
the memory semantics of it. Suddenly "volatile" is a relevant
modifier of a local variable. Well, some of them. :) (Right?)

opinali

unread,
Sep 15, 2011, 2:25:10 PM9/15/11
to java...@googlegroups.com
On Thursday, September 15, 2011 11:17:43 AM UTC-4, Josh Berry wrote:

Just lifting the variable to a field means you have completely moved
the memory semantics of it.  Suddenly "volatile" is a relevant
modifier of a local variable.  Well, some of them. :)  (Right?)

The current language does not allow 'volatile' for local variables; so lifting a local variable to a non-volatile field (the most straightforward implementation) would not have any JMM consequences. But that's the point where Oracle claims that mutable capture is bad, because the programmer could possibly use the closure in multithreaded code and then we need to worry about JMM. My preferred solution is just allowing 'volatile' as a modifier for all locals; if you use that on a non-captured local, then the modifier is ignored, but if you use it on a local that's captured by a closure, then it's lifted to a volatile field. This solution is orthogonal: no special case for captured vs. non-captured, the non-captured case is an optimization because it is visible to a single thread so it behaves like a volatile field without needing any memory barriers. And this solution allows you to solve concurrent programming issues just like you'd do for equivalent code without closures; the captured local would be explicitly marked as volatile and then it's up to you to use it correctly. I would concede to have a default javac warning for mutable locals that are closure-captured but lack the 'volatile' modifier; this should be good enough to make closures very friendly to concurrent programming, even at the expense of needing an annoying @SuppressWarning annotation for the cases where volatile is not necessary because the closure will only be invoked in the same thread of its instantiation (it wouldn't be hard for javac to detect some of these cases - just do escape analysis at the javac level - then the warning could be automatically suppressed).

A+
Osvaldo

clay

unread,
Sep 15, 2011, 5:15:58 PM9/15/11
to The Java Posse
@opinali,

"the major point of debate is whether Java's closures (with or without
Java 8's lambdas) are 'good enough'"

That's an important issue, but I want something less than that: I want
people to communicate their thoughts and viewpoints using technically
meaningful language.

The Java Posse have repeatedly said "Java doesn't have closures",
"Scala is basically Java with closures", "Java really needs closures".
People are basically misusing the word closure to represent a variety
of different issues and language features. My point is that you should
use correct language so we can understand each other. If you think
Java is terrible because it doesn't have first class functions or
continuations, say that rather than use your own personal definition
of the word "closure" and expect everyone to know what you are talking
about.

I think you, I, and most people in this thread have come to a
reasonable consensus: Java absolutely has a limited but useful
implementation of closures that is widely used. Moving forward, Java
sorely needs to be improved in a variety of ways. That's a much bigger
topic but for starters Java needs better closures and they should be
married with first class functions and a better syntax for anonymous
functions. Java should also have better support for side-effect
immutable programming and have a high quality persistent immutable
data collection library (guava has constant read only collections but
not persistent immutable collections like Scala does).

Ricky Clarkson

unread,
Sep 15, 2011, 5:55:28 PM9/15/11
to java...@googlegroups.com
I disagree that the C# example is contrived, having accidentally made the mistake they show.

On Thu, Sep 15, 2011 at 9:37 AM, opinali <opi...@gmail.com> wrote:
To view this discussion on the web visit https://groups.google.com/d/msg/javaposse/-/W8qWzFi4XtoJ.

opinali

unread,
Sep 15, 2011, 7:13:28 PM9/15/11
to java...@googlegroups.com
On Thursday, September 15, 2011 5:55:28 PM UTC-4, Ricky Clarkson wrote:
I disagree that the C# example is contrived, having accidentally made the mistake they show.

Still, this is just an isolated anecdote. I have already made my fair share of bugs, in virtually all categories, since I started programming... and I won't claim that Java's traditional for loop is broken because I have made some off-by-one errors.

Any kind of bug can appear to be much more important (easy to make) when you are not very familiar with some new programming idiom. I'm not a C# guy but I know that closures are a relatively new feature, added only in C# 3.0, so I suppose their use is not as intense as in systems that adopted closures since day zero in the language and core libraries. But let's invert the perspective: suppose some Smalltalk diehard comes to us and claims that any language that doesn't have a numerical tower is broken, because without that, programmers will make bugs like overflow or unintended loss of precision all the time. Maybe this is true for a Smalltalker that is transitioning to languages like C/C++/C#/Java, but it's certainly not true for a veteran in those languages. I for one, sincerely have no memory of *ever* having made an integer overflow bug in my entire professional life. (Not really bragging - I've started learning programming at 13yo, with Assembly no less, so my instincts for low-level decisions like picking the correct numeric precision for each variable were already very sharp by the time I started working...)

There is zero evidence that I know of, that closure-capture of mutable variables are a significant risk of bugs (higher than reasonable, considering that any language feature allows some kind of bugs). We have 50 years of industry experience since Lisp in 1959+, and I don't think the whole problem was ever discussed at all before Java made the entire concept of closures subject of heated debate for the first time. Paraphrasing the very funny blog http://james-iry.blogspot.com/2009/05/brief-incomplete-and-mostly-wrong.html, "Java has made full closures questionable by not having them..."

A+
Osvaldo
 

--
Skype: ricky_clarkson


--
Skype: ricky_clarkson


To unsubscribe from this group, send email to java...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To view this discussion on the web visit https://groups.google.com/d/msg/javaposse/-/Fff1UZB3f5EJ.

To post to this group, send email to jav...@googlegroups.com.
To unsubscribe from this group, send email to javapo...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.

opinali

unread,
Sep 15, 2011, 7:51:40 PM9/15/11
to java...@googlegroups.com
i clay,

True we agree on most "concrete" points :) I'll only make a fix, there is no such a thing as my "personal defintion of closure"; in another message here I defined closure as "the pairing between a function and an environment that provides bindings to its free variables" - this definition is not subject to debate, sorry. But that definition is vague enough to not include details like whether mutable vars should be captured - precisely because these details are distinct across languages (e.g. some languages do not have mutable variables at all; other important features that interact with closures in some languages: continuations, tail calls, MOPs...).

We disagree in higher-level, philosophical terms. But these are not unimportant. I insist a lot in the concept of orthogonality, and this is important because it boils down to complexity. Failures in orthogonality cause a language to be more complex; this also is not opinion ("orthogonality" translates to "all pieces work together seamlessly"). And in this case we're talking about complexity that is unnecessary (because the solution is simple and VERY time-proven), and has no significant positive tradeoffs. Yeah, Oracle claims that safer concurrency is such tradeoff, but that's bollocks. People will just keep using hacks like creating a final single-element array so it can be captured by the closure, and if the code is concurrent that will be a bug because you can't make an array *element* volatile. Then the programmer fixes that to use an Atomic object... but that's still a bit of a hack, needing a special API instead of a fundamentnal language construct for that. The whole problem would not exist at all with mutable capture: no new technique would be ever necessary, the programmer wouldn't need to learn anything new to make concurrency safe with closures (just use volatile if the code is multithreaded - exactly like you would do without closures).

I wholeheartedly agree that Java could benefit from steps towards functional idioms, but this is a completely distinct discussion, and such improvements cannot be made at the expense of the existing language, which core is "purely imperative" and (whether we like it or not) will always be.

A+
Osvaldo
Reply all
Reply to author
Forward
0 new messages