Is this a limitation of java lambda in design

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

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

For this simple case, I have two options:

  • Define a functional interface. The only abstract method should be int add(int a, int b,int c) , method names and variable names do not matter.

  • Use the link to the method. 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 simplest lambda, I need to return to the world of OOP (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

+5
source share
4 answers

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

So yes, you must return to the world of OOP.

However, you can use the built-in Function type to define your function in its expressed form:

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

Using:

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

Although I doubt that it is readable at all ...

+5
source

Actually, the definition of a function in Scala works in exactly the same way as option 1, except for 1) the functional interface of scala.Function3[A1, A2, A3, B] contained in the Scala standard library; 2) the compiler fakes the Int support in generics (which ends with the conversion to the java.lang.Integer box.

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

Scala benefits from type inference, of course, in two ways:

  • FunctionN is the default functional interface for lambda expressions, so it does not need to be specified.

  • If you specify arguments, the return type can usually be inferred.

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

+5
source

In your specific use case, where the type of operation and the operand are the same at the same time (a + b + c => a + (b + c)), you can use BiFunction defined as: -

 BiFunction<Integer, Integer, Integer> f = (x, y) -> x + y; System.out.println(f.apply(a, f.apply(b, c))); // a + b + c 

Or another alternative suggested by @Igor should be used for sum over IntStream .

+2
source

You are looking for the following:

 int sum = IntStream.of(a, b, c).sum(); 
+1
source

Source: https://habr.com/ru/post/1272900/


All Articles