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.

On Tue, Sep 13, 2011 at 12:04 PM, Josh Berry <[email protected]> wrote:

> On Tue, Sep 13, 2011 at 11:31 AM, clay <[email protected]> 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.
>
> --
> You received this message because you are subscribed to the Google Groups
> "The Java Posse" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> 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 [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en.

Reply via email to