Monday, April 02, 2007

Extended Type-Cast vs. Closures vs. Current Java

Although I'm not a fan of messing up the Java language, I had another idea, I'd like to share:

An extended type-cast for single-method interfaces, which succeeds if the signatures are compitable. More precise, the target's method could be overridden by the one of the source interface, the syntax could be: (A as B)
(Note: contravariant arguments would be also possible)

I guess it's is highly related to the ongoing debate if and how to integrate closures (CICE, FCM and BGGA). Although, I think the last one has its pros and I really like the idea of first-class methods (place my vote here), the remaining one really has a mighty ally: simplicity.

However, the absense of method/functions type, which can be assigned only depending on their signature types, makes it look a bit clumsy. With the proposed extended type-cast, things would be more balanced as this example shows.



Just, for those who didn't have noticed yet, the main thing is (Bar as Foo), but it looks nicer within the other syntax sugar as well:
  • calling the single method of an interface, its name can be omitted
  • simplifyedcreation of anonymous classes, which implement single-method interfaces
  • usage of var/final instead of specifying the reference type


EDIT: Modified the source to match the BGGA proposal accoringly to Neal Gafter's comment.

4 comments:

Neal Gafter said...

Correction:

void closures(A a) {
( String => Integer ) bar = { String arg => arg.length() };
( String => Number ) foo = bar;
a.method(foo);
}

or, more simply

void closures(A a) {
a.method({String arg => arg.length});
}

Unknown said...

Thank you for the comment!

I modified the code with the first correction. Not the simplified version, because I wanted to emphasize on conversion/casting and the othter could be shortened that way too:

current:

a.method( new Foo() { public Number foo(String arg) { return arg.length(); } });


proposed:

a.method(new Foo.foo(String arg) { return arg.length(); });

Ricky Clarkson said...

With method references from FCM, you could do this without anything extra.

Given interface X { double flop(double t); }

and the identical but differently named interface Y { double flap(double t); }, you could pass a reference to flop to a method that expects a Y:

X x=createX();
call(x#flop(double));

Unknown said...

But does the FCM proposal define conversion for 'compatible' methods? For example, would the following be possible:

#(Number(String)) refA = ..
#(Integer(Object)) refB = refA;

BGGA does as well as the extended type-cast.


Anyway, I believe FCM could - or does already? - support this, but IMHO the proposal adds far to much unessecary stuff to the language. Don't get me wrong, I really like the idea of FCM, but not the anonymous methods:

#(Integer(int)) intToInteger;


I prefer explicit types, like:

interface IntToInteger { Integer function(int value); }

with optional syntax sugar:

interface IntToInteger(int value) Integer;

to use with FCMs:

IntToInteger ref = Integer#valueOf(int);


This approach does not only fit better to the current language style, but it also can reduce code: Imagnie methods with long parameter lists. Often a compatible interface exists already, and if not it only has to defined (the signature written once).