Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smooth way of using Function<A, R> java interface from scala?

Here at work most people use Java, while I am working with Scala. We have decided to gather some common classes in an library which will be written in Java. Now I want to add some pseudo-functional programming to the library, take a look at the following:

java:

public interface Func<A, R> {
    public R f(a A);
}

public AClass {
    public <R> ArrayList<R> myMethod(
                             Func<String, R> func
    ) {
        // ...
    }
}

usage in java:

AClass ac = new AClass();
ArrayList<String> al = ac.myMethod(
                            new Func<String, String> (
                                public String f(String s) {
                                    return s + "!";
                                }
                            })

The above is not exactly exiting (more like daunting actually, from a scala perspective). Is there any way to summon some scala magic to be able to do something like the following in scala:

var ac = new ACLass
var al = ac.myMethod(str => str + "!")             // alternative 1
al = ac.myMethod { case: str:String => str + "!" } // alternative 2

I messed around with implicits for a while but couldn't get things sorted out =P.

like image 460
fickludd Avatar asked Sep 20 '11 06:09

fickludd


3 Answers

With implicit conversions:

object FuncConversions {
  implicit def func2function[A,R]( fn: (A) => R ) =
    new Func[A,R] {
      def f(a: A) = fn(a)
    }
}

Don't forget to import the conversion in your scope:

import FuncConversions._

You can also implement the opposite conversion.

like image 52
paradigmatic Avatar answered Sep 30 '22 22:09

paradigmatic


To expand on paradigmatic answer. Here is how you go about figuring out the implicit. Implicit conversions come into play when the types don't check. When that happens, the compiler will search for an implicit conversion to use so that types match.

After cleaning up your example a bit, in the REPL, the compiler would show:

scala> ac.myMethod((s:String) => s + "!")
<console>:9: error: type mismatch;
 found   : String => java.lang.String
 required: Func[java.lang.String,?]
              ac.myMethod((s:String) => s + "!")

So the compiler tells you it found a (String) => (String) but needs a Func[String, ?]. Therefore you want to provide an implicit conversion between the found type and the required type. So the signature should be something like:

implicit def fun2Func(fun: (String) => String): Func[String,String]

Then, the next step is to realize that the implicit conversion can be generalized with types A and R.

On a sidenote, I wonder if you'd be better of by re-using something of the shelf like http://code.google.com/p/guava-libraries/.

like image 36
huynhjl Avatar answered Sep 30 '22 23:09

huynhjl


I don't know exactly but maybe functional Java http://functionaljava.org/ could help you and your collegues. What functions exactly you try to gather in your 'pseudo-fp' lib?

like image 42
AndreasScheinert Avatar answered Sep 30 '22 22:09

AndreasScheinert