- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Using Scala higher-order functions from Java (and using Java 8 lambda syntax)
Sat, 2011-12-03, 18:47
I’d like to find the less boilerplate way to use Scala higher-order functions from Java and possibly to be able to use the Java 8 lambda syntax (e.g.: n -> n + 1).I found this thread: http://stackoverflow.com/questions/6545066/using-scala-from-java-passing-functions-as-parametersBut it does not seem to apply currently (probably because of the @specialized annotation on scala.Function1?), here is the error message I get if I try to compile the following code:
Option<Integer> opt = new Some<Integer>(42); System.out.println(opt.map(new Function1<Integer, String>() {
public int $tag() { return Function1$class.$tag(this); } public <A> Function1<A, String> compose(Function1<A, Integer> f) { return Function1$class.compose(this, f); } public String apply(Integer n) { return n.toString(); } }));
> compile[info] Compiling 1 Java source to /home/julien/Workspace/lambda-test/target/scala-2.9.1/classes...[error] /home/julien/Workspace/lambda-test/src/main/java/lambda/Lambda.java:21: error: <anonymous lambda.Lambda$2> is not abstract and does not override abstract method <A>andThen$mcVJ$sp(Function1<BoxedUnit,A>) in Function1[error] System.out.println(opt.map(new Function1<Integer, String>() {[error] ^[error] where A is a type-variable:[error] A extends Object declared in method <A>andThen$mcVJ$sp(Function1<BoxedUnit,A>)[error] /home/julien/Workspace/lambda-test/src/main/java/lambda/Lambda.java:23: error: cannot find symbol[error] return Function1$class.$tag(this);[error] ^[error] symbol: variable Function1$class[error] /home/julien/Workspace/lambda-test/src/main/java/lambda/Lambda.java:27: error: cannot find symbol[error] return Function1$class.compose(this, f);[error] ^[error] symbol: variable Function1$class[error] 3 errors
So I tried to find another way by myself and ended with the following:
// JFunction1.javapublic interface JFunction1<T1, R> { R apply(T1 t);}
// function.scalaobject JFunction { def fun[T1, R](g: JFunction1[T1, R]): T1 => R = new (T1 => R) { override def apply(t: T1) = g.apply(t) }}
// MainApplication.java Option<Integer> opt = new Some<Integer>(42); // Java 7 anonymous class syntax System.out.println(opt.map(JFunction.fun(new JFunction1<Integer, String>() { @Override public String apply(Integer n) { return n.toString(); } }))); // Java 8 lambda syntax System.out.println(opt.<String>map(JFunction.<Integer, String>fun(n -> n.toString())));
This code works, here are some notes: — The JFunction1 interface seems to be mandatory to allow the Java 8 lambda syntax ; — Using the lambda syntax I need to explicitly write the parameter and return types.
Is there a less boilerplate way to write scala.Function1 objects from Java and possibly using the Java 8 lambda syntax?
Option<Integer> opt = new Some<Integer>(42); System.out.println(opt.map(new Function1<Integer, String>() {
public int $tag() { return Function1$class.$tag(this); } public <A> Function1<A, String> compose(Function1<A, Integer> f) { return Function1$class.compose(this, f); } public String apply(Integer n) { return n.toString(); } }));
> compile[info] Compiling 1 Java source to /home/julien/Workspace/lambda-test/target/scala-2.9.1/classes...[error] /home/julien/Workspace/lambda-test/src/main/java/lambda/Lambda.java:21: error: <anonymous lambda.Lambda$2> is not abstract and does not override abstract method <A>andThen$mcVJ$sp(Function1<BoxedUnit,A>) in Function1[error] System.out.println(opt.map(new Function1<Integer, String>() {[error] ^[error] where A is a type-variable:[error] A extends Object declared in method <A>andThen$mcVJ$sp(Function1<BoxedUnit,A>)[error] /home/julien/Workspace/lambda-test/src/main/java/lambda/Lambda.java:23: error: cannot find symbol[error] return Function1$class.$tag(this);[error] ^[error] symbol: variable Function1$class[error] /home/julien/Workspace/lambda-test/src/main/java/lambda/Lambda.java:27: error: cannot find symbol[error] return Function1$class.compose(this, f);[error] ^[error] symbol: variable Function1$class[error] 3 errors
So I tried to find another way by myself and ended with the following:
// JFunction1.javapublic interface JFunction1<T1, R> { R apply(T1 t);}
// function.scalaobject JFunction { def fun[T1, R](g: JFunction1[T1, R]): T1 => R = new (T1 => R) { override def apply(t: T1) = g.apply(t) }}
// MainApplication.java Option<Integer> opt = new Some<Integer>(42); // Java 7 anonymous class syntax System.out.println(opt.map(JFunction.fun(new JFunction1<Integer, String>() { @Override public String apply(Integer n) { return n.toString(); } }))); // Java 8 lambda syntax System.out.println(opt.<String>map(JFunction.<Integer, String>fun(n -> n.toString())));
This code works, here are some notes: — The JFunction1 interface seems to be mandatory to allow the Java 8 lambda syntax ; — Using the lambda syntax I need to explicitly write the parameter and return types.
Is there a less boilerplate way to write scala.Function1 objects from Java and possibly using the Java 8 lambda syntax?
Mon, 2011-12-05, 04:27
#2
Re: Using Scala higher-order functions from Java (and using Jav
On Sat, Dec 3, 2011 at 12:47 PM, Julien Richard-Foy wrote:
> I’d like to find the less boilerplate way to use Scala higher-order
> functions from Java [...]
scala.runtime.AbstractFunction1 (and so on for other arities) makes
this much easier:
$ cat J.java
import scala.runtime.AbstractFunction1;
import scala.Some;
import scala.Option;
public class J {
public static void main(String[] args) {
Option opt = new Some(42);
System.out.println(opt.map(new AbstractFunction1() {
public String apply(Integer n) {
return n.toString();
}}));
}
}
$ javac -classpath /usr/local/scala-2.9.1.final/lib/scala-library.jar J.java
$ java -classpath .:/usr/local/scala-2.9.1.final/lib/scala-library.jar J
Some(42)
Mon, 2011-12-05, 23:47
#3
Re: Using Scala higher-order functions from Java (and using Jav
Using scala.runtime.AbstractFunctionN is indeed very interesting with Java 7, but it does not seem to be used with the lambda expression syntax of Java 8:required: AbstractFunction1<T1,R> found: <lambda> reason: actual argument <lambda> cannot be converted to AbstractFunction1<Integer,String> by method invocation conversion (the target type of a lambda conversion must be an interface)
I created a gist for more reading comfort: https://gist.github.com/1427697