Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a limitation of java lambda in design

Tags:

java-8

scala

I want to define a simple lambda, add up three integers:

(int a, int b,int c)->a+b+c

For this simple case, I have two options:

  1. Define a functional interface. The single abstract method should be int add(int a, int b,int c), the method name and varable names don't matter.

  2. Use method reference. I have to define a class/method or use an existing method that has the signature int add(int a, int b,int c)

In both cases, for the very simple lambda, I have to get back to the OOP world(interface, class, etc)

But in scala, it is very simple to define a function in place: val add= (a:Int,b:Int,c:Int)=>a+b+c

like image 225
Tom Avatar asked Oct 26 '17 03:10

Tom


2 Answers

In Java, you must target every lambda expression to a specific functional interface type. This is by design, and in practice it means that functions are not first-class citizens of the language.

So, yes, you have to get back to OOP world.

You can, however, use the Function built-in type to define your function in its currified form:

Function<Integer, Function<Integer, Function<Integer, Integer>>> add =
    a -> b -> c -> a + b + c;

Usage:

int result = add.apply(1).apply(2).apply(3); // 6

Though I doubt this is readable at all...

like image 69
fps Avatar answered Oct 16 '22 16:10

fps


Actually, defining a function in Scala works exactly the same as option 1, except 1) the functional interface scala.Function3[A1, A2, A3, B] is contained in the standard Scala library; 2) the compiler fakes supporting Int in generics (which ends up being converted to boxed java.lang.Integer.

You can't really do anything about 2) in Java, but 1) is solved trivially by using a library which defines Function3 and so on (or writing your own). There are http://www.functionaljava.org/, http://www.vavr.io/, https://mvnrepository.com/artifact/uk.org.potes.java8/java8-currying (which only has those interfaces and nothing more). Probably a few others.

Scala wins on type inference, of course, in two ways:

  1. FunctionN is the "default" functional interface for lambda expressions, so it doesn't need to be specified.

  2. If you specify arguments, return type can normally be inferred.

But these considerations matter more when assigning lambdas to a field or a variable, and less when passing them to a method, which is probably more common.

like image 31
Alexey Romanov Avatar answered Oct 16 '22 17:10

Alexey Romanov