#417 Java FFI: coercions from sys::Func to Java interfaces

brian Thu 18 Dec 2008

One of the last missing pieces I'm working on is how to utilize Fan's functional constructs as a convenience where you'd typically use an inner class in Java. Since Java doesn't yet have function types nor has any clear proposal for closures emerged, we have to make do with what is there today.

My thinking is that a Fan expression typed as sys::Func can be used anywhere a Java class or interface is expected, and the Java type has exactly one abstract method. Under the covers we will box the function to a wrapper class which implements the Java type and calls the function:

// Java API:
void foo(Runnable r) { r.run(); }

// Fan code:
func := |,| { echo("run") }
foo(func)

// Result:
foo(FuncWrapperX(func))

class FuncWrapperX : Runnable
{
  new make(Func f) { _func = f }
  override Void run() { _func.call0 }
  Func _func
}

Comments?

Edit: actually I think we allow coercion only when a Java interface with exactly one method is expected. We don't support coercion to a class with one abstract method - that is a bit complicated and doesn't seem like a very common use case.

andy Thu 18 Dec 2008

Makes sense to me.

brian Thu 18 Dec 2008

I got this feature all working and pushed to hg to be included into the next build. Now you can do cool things like:

button := JButton("Press Me!")
{
  addActionListener |ActionEvent e| { echo("Button pressed!") }
}

tompalmer Fri 19 Dec 2008

Great news.

jodastephen Fri 19 Dec 2008

There is a weird edge case in Java. This is where an interface as multiple abstract methods, but all but one of them are methods declared in Object, thus not really abstract. IIRC, Comparator is the classic example of this, defining equals() and hashCode() as well as compare(). Clearly, only the compare() method is truly abstract, so can be treated as convertible for functions.

JohnDG Fri 19 Dec 2008

This is very cool!

brian Fri 19 Dec 2008

There is a weird edge case in Java. This is where an interface as multiple abstract methods, but all but one of them are methods declared in Object

I could certainly handle that, but Comparator turns out to be a weird Fan edge case because compare conflicts with sys::Obj.compare. Conflicts with the "Object" base class between the various languages probably still needs some work.

alexlamsl Sat 20 Dec 2008

Looking at java.lang.Comparable, java.util.Comparator and System.Collections.IComparer, looks like a simple solution would be to rename sys::Obj.compare to sys::Obj.compareTo and updates the relevant links to operator overloading...

brian Sat 20 Dec 2008

simple solution would be to rename sys::Obj.compare to sys::Obj.compareTo

We can't do that because the Fan signature which returns sys::Int maps to a long return type (not an int which Java requires). Actually that is why I originally picked a different name.

Login or Signup to reply.