 |
Syntax of closure
Posted by forax on August 31, 2006 at 06:37 AM | Comments (12)
In forum (fora) and blogs, i have often seen that closures are compared to anonymous classes
in order to reject the proposed syntax of closure.
In this entry, i try to show up why the closure syntax
is such as it is by explaining the differences with the
anonymous class syntax.
Let me introduce an example that sort a list of integers
in reverse order.
There are two codes, one written with an anonymous class
and the other written with a closure using the closure convertion.
The code using a closure:
List<Integer> list=Arrays.asList(666,7,12);
Collections.sort(list,int(Integer i1,Integer i2) {
if (i1<i2)
return 1;
else
if (i2<i1)
return -1;
return 0;
});
And the code using an anonymous class:
List<Integer> list=Arrays.asList(666,7,12);
Collections.sort(list,new Comparator<Integer>(){
public int compareTo(Integer i1,Integer i2) {
if (i1<i2)
return 1;
else
if (i2<i1)
return -1;
return 0;
}
});
I've found five differences and all have a reason so
i don't see why people want to change the proposed syntax.
A step by step comparison
- An anonymous class starts with new,
because it always create a new object, closure can reuse
the same singleton so no "new".
- an anonymous class takes a type (a class, an abstract
class or an interface), closure doesn't need to specify
a type because the compiler infers the type.
Due to an implementation detail, closure convertion can
only occur with an interface.
- an anonymous class must parameterize its constructor
(Comparator<Integer>). Closure can infer the
value of the type variable. Because of the backward
compatibility of generics,
the compiler must be able to distinguish a raw type from a
parametrized type so the type variable of an anonymous class
can't be infered.
- an anonymous class can take arguments,
a closure can't because as state above,
a closure can only implements an interface.
- an anonymous class need to specify access modifier (public)
and the method name. The closure have only one public method
so it's neither necessary to name it
nor to specify a modifier.
I hope this entry will reconcile the grimpies with the proposed
syntax.
Wow, this is my fourth entry about closure,
it's time for me to register with CA (Closure Anonymous) :)
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
Er, shouldn't your code samples be the other way around?
Posted by: voorth on August 31, 2006 at 07:12 AM
-
Hmmm
An anonymous class always (acts as if) a new object was created. So there is no need to specify that. Likewise, if you call a static creation method, you don't use new.
If an anonymous class is taking the role of a closure, then the base type can be inferred. So there is no need to require anonymous classes to specify base types.
The argument that raw and parameterised types need to be distinguished in constructors is just staggeringly lame.
Anonymous classes can implement interfaces. So these don't need to specify constructor arguments.
I really don't see the need to require anonymous classes to specify access modifiers. Who's going to see it?
So, when anonymous inner classes are used where they could be replaced by closures, the extra syntactical baggage is only there to fit the old grammar.
Posted by: tackline on August 31, 2006 at 07:36 AM
-
1. If optimizer works, there is no memory allocation in 'new'.
Posted by: yozh on August 31, 2006 at 08:05 AM
-
yozh: I think the point is that you cannot tell whether an anonymous inner class has been created on the heap or some escape analysis magic has happened. If you create two instances of an inner class, == between them will always be false and the intrinsic lock will be different.
Posted by: tackline on August 31, 2006 at 08:38 AM
-
Recent edits to the original proposal indicate your closure example may be inaccurate. If I've understood correctly, the new proposal is that the 'return' statements within the closure will return from the surrounding method, not from the sort method. And thus a different syntax is needed for returning a value within the sort method. (See Neal Gafter's blogs). Hence, I believe the closure example should be as follows:
List list=Arrays.asList(666,7,12);
Collections.sort(list,int(Integer i1,Integer i2) {
int result = 0;
if (i1<i2)
result = 1;
else
if (i2<i1)
result = -1;
result;
});
Which is of course quite a change...
Posted by: scolebourne on August 31, 2006 at 09:26 AM
-
@voorth, oups, corrected now.
@scolebourne, yes, i've read the Neal's blog and i was not convinced
by this new syntax. I prefer the old one.
Rémi
Posted by: forax on August 31, 2006 at 01:02 PM
-
@tackline,
what i try to explain is why the closure syntax is like this.
What you says is that the anonymous class syntax can be
changed. i'm ok with that.
As you said, an anonymous class always creates a new object,
so it seems ok for me that the syntax uses "new".
see general comment
ugh, it seems a good argument for me
yes
reflexion, hand coded bytecode (security !)
Rémi
Posted by: forax on August 31, 2006 at 01:36 PM
-
In:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6389769
I suggest shorter syntax for common operations, including inner classes. Your example would become:
Collections.sort( list, Comparator() ( i1, i2 ) {
if ( i1 < i2 ) return 1;
else if ( i2 < i1 ) return -1;
return 0;
} );
(Assuming that type inference on constructors was put in, i.e. raw type would be Comarable<>; if not add < Integer >.) Either way the syntax is similar to that for closures and doesn't entail adding a new concept.
Posted by: hlovatt on August 31, 2006 at 06:05 PM
-
I confess that I'm not sold on this proposal yet -- what are the advantages over (say) hvlovatt's proposed syntax above?
Posted by: enicholas on September 07, 2006 at 06:05 AM
-
The syntax proposed by hvlovatt' is not realistic,
i1 and i2 can be int, long, short and even Integer, Long etc,
however Comparator is inferable.
Remi
Posted by: forax on September 07, 2006 at 08:38 AM
-
@Remi,
I think the syntax I have proposed is possible, it requires no more type inference than Java currently does for methods (but currently does not do for constructors). The keys are:
Comparator has only one undefined method and therefore the method signature is easy to infer, as: int compare(T o1, T o2).
Java currently infers T for sort, who's definition is: static <T> void sort(List<T> list, Comparator<? super T> c), from the argument list. This T is then used for Comparator<T> and hence compare(T o1, T o2).
If T is not a boxed numeric type then there is an error. Just like at present if you were to write this out long hand.
The key to the proposal is that it is mainly syntax sugar (perhaps a tweak to type inference). But certainly a much smaller change than the proposed closure addition.
Posted by: hlovatt on September 07, 2006 at 07:06 PM
-
@hlovatt, inference is a bottom-up mecanism, so with your closure :
Comparator() ( i1, i2 ) {
if ( i1 < i2 ) return 1;
else if ( i2 < i1 ) return -1;
return 0;
}
you need to determine i1 and i2 with what you have written
between { and }.
Remi
Posted by: forax on September 08, 2006 at 12:36 AM
|