This question already has answers here:
Java 8: Where is TriFunction (and kin) in java.util.function? Or what is the alternative?
(12 answers)
Closed 1 year ago.
I read many examples about how to easily define a lambda in Java 8. This lambda takes always one parameter like f1:
Function<Integer,Integer> f1 = (x) -> Math.pow(x,2);
Of course, you can extend the body like f2:
Function<Integer,Integer> f2 = (x) -> {if (x < 0) return 0;
else return Math.pow(x,2);};
But I cannot find a way to define a lambda with a variable number of paramters like f3:
Function<Integer,Integer,Integer> f3 = (x,y) -> {return x + y};
or without parameter like f4:
Function<Double> f4 = () -> {return Math.random()};
I am almost sure that you can define own functional interface (i.e., create a new file commonly) to develop f3 and f4, but Is there some way to easily define them?
Function<Integer,Integer,Integer> f3 = (x,y) -> {return x + y};
is actually a BiFunction<Integer,Integer,Integer>
and
Function<Double> f4 = () -> {return Math.random()};
is a Supplier<Double>
If you need more create your own, like TriFunction<Integer,Integer,Integer,Integer> for example
I am almost sure that you can define own functional interface (i.e.,
create a new file commonly) to develop f3 and f4, but Is there some
way to easily define them?
In addition to the Eugene answer, I would add that :
Function<Integer,Integer,Integer> f3 = (x,y) -> {return x + y};
may be considered as BiFunction<Integer,Integer,Integer> or simply BinaryOperator<Integer>.
Note that you perform arithmetical computations with the Integers in the lambda body. These produce unboxing and boxing operations : Integer->int->Integer. So in this use case you are encouraged to use a specialized functional interface that prevents that : IntBinaryOperator which the functional signature is (int, int)-> int that is itself a specialization of BinaryOperator<T> a subclass of BiFunction<T,T,T>
In the same logic of sparing autoboxing operations :
Function<Integer,Integer> f2 should be IntFunction f2
and Supplier<Double> f4 should be DoubleSupplier f4.
Note also that specifying a specific number of argument makes sense as it is straight usable in a lambda body but specifying something like a var-args is possible but generally harder to exploit.
For example you could declare this interface :
#FunctionalInterface
public interface VargsFunction<T,R> {
#SuppressWarnings("unchecked")
R apply(T... t);
}
But harder to use without delegating to a method that accepts a var-args :
VargsFunction<Integer, Integer> f = varg-> call(varg);
Integer call(Integer... varg) {
...
}
A function that takes two arguments is a BiFunction:
BiFunction<Integer, Integer, Integer> f3 = (x, y) -> x + y;
A function that takes no arguments is a Supplier:
Supplier<Double> f4 = () -> Math.random();
or equivalently:
Supplier<Double> f4 = Math::random;
Related
This question already has answers here:
Pass function as reference to another method in Java [duplicate]
(2 answers)
How can we have 2 parameters in java.util.function.Function lambda?
(2 answers)
Closed 1 year ago.
I'm coming from C++ and I feel a little bit frustrated and confused. I was googling for help for a while and I still can't find an answer, so I am here.
How in Java can I implement a NavigableMap<String, ?> where at the question mark is an object which can be called with two arguments and then return a value.
I would like it to look like so:
NavigableMap<String, SomeFunctorClass> container;
// I also don't know how to write a lambda thing in java, so it won't work.
// [](double a, double b) -> double { return a + b; } // in C++
container.put("add", (double a, double b) -> { return a + b; });
// Expected to be 10.
double result = container.get("add")(4, 6);
The equivalent in java is a BiFunction:
NavigableMap<String, BiFunction<Double, Double, Double>> container;
container.put("add", (a, b) -> a + b);
Note that generics in Java cannot be primitive, so you should use the boxed versions (Double for double, Integer for int etc.)
If you need more than 2 parameters (for example a TriFunction), then you'll need to create your own interface since Java standard library doesn't offer more than that (it's not as extensible as C++).
As for the way of calling it:
// Expected to be 10.
double result = container.get("add").apply(4.0, 6.0);
The closest thing Java offers out of the box is probably a BiFunction.
You still won't be able to call it directly with () like you'd do on a C++ functor, but you can call its apply method:
NavigableMap<String, BiFunction<Double, Double, Double>> container = new TreeMap<>();
container.put("add", (a, b) -> a + b);
double result = container.get("add").apply(4.0, 6.0);
Let's say that I have function Object f(String a, String b) and I want to call two different functions that return Optional Strings to get the parameters for f Optional<String> getA() and Optional<String> getB(). I can think of two solutions but neither look all that clean, especially when you have even more parameters:
1:
return getA().flatMap(
a -> getB().map(
b -> f(a,b)).get()
2:
Optional<String> a = getA();
Optional<String> b = getB();
if(a.isPresent() && b.isPresent()) {
return f(a.get(), b.get());
}
Is there a cleaner way to do this?
You've just stumbled upon a concept called lifting in functional programming, that enables you to lift regular functions (e.g. A -> B) into new domains (e.g. Optional<A> -> Optional<B>).
There's also a syntactic sugar for flatMapping and mapping more comfortably called the do notation in Haskell and similar languages, and for comprehension in Scala. It gives you a way to keep the flow linear and avoid nesting (that you were forced to go through in your example 1).
Java, unfortunately has nothing of the sort, as its functional programming capabilities are meager, and even Optional isn't really a first-class citizen (no standard API actually uses it).
So you're stuck with the approaches you've already discovered.
In case you're curious about the concepts mentioned above, read on.
Lifting
Assuming you have:
public String f(A a, B b) {
return b + "-" + a;
}
With its Scala equivalent:
def f(a: A, b: B) = b + "-" + a
Lifting f into Option (same as Optional in Java) would look like this (using Scalaz library, see here for Cats)
val lifted = Monad[Option].lift2(f)
lifted is now a function equivalent to:
public Optional<String> f(Optional<A> a, Optional<B> b) {
if(a.isPresent() && b.isPresent()) {
return Optional.of(b + "-" + a);
}
return Optional.empty;
}
Exactly what you're looking for, in 1 line, and works for any context (e.g. List, not just Option) and any function.
For comprehension / Do notation
Using for comprehension, your example would look like this (I think, my Scala is weak):
for {
a <- getA();
b <- getB();
} yield f(a, b)
And again, this is applicable to anything that can be flatMapped over, like List, Future etc.
You could stream the arguments and apply the condition only once, but whether or not this is more elegant than your solutions is in the eye of the beholder:
if (Stream.of(a, b).allMatch(Optional::isPresent)) {
return f(a.get(), b.get());
}
I'm of the opinion that if there is no good way to use Optional, then there is no reason to try to use it anyway.
I find this to be cleaner and simpler than your option 2:
String a = getA().orElse(null);
String b = getB().orElse(null);
if(a != null && b != null) {
return f(a, b);
}
If you are sure that a and b are both present (as your final call to get in solution 1 seems to suggest), I think it is pretty straightforward:
return f(getA().orElseThrow(() -> new NoSuchElementException("a not present")),
getB().orElseThrow(() -> new NoSuchElementException("b not present")));
If you aren’t sure that both are present, I would prefer your solution 1. It exploits Optional the best. Only I would not call get at the end, but rather orElse or what makes sense in your situation, for example:
return getA()
.flatMap(a -> getB().map(b -> f(a,b)))
.orElse("Not both present");
There's a default method andThen() in the BiFunction interface (java.util.function package).
default <V> BiFunction<T,U,V> andThen(Function<? super R,? extends V> after)
The documentation says:
Returns a composed function that first applies this function to its input, and then applies the after function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the composed function.
It's little confusing to understand what the explanation means. As per my understanding, a composed function is returned when the default andThen() method is invoked. This composed function is invoked on the types T and U that returns the type V. Finally, there's and after function that is invoked on the types R and V.
What's the need of this method? How does it actually fit in the picture?
It's little confusing to understand what the explanation means.
To explain it as simple as I can, the method andThen returns a function that first applies a given function to an input and then applies another function to the result of that application.
Assume we had two functions f and g , function f doing some logic and function g doing some other type of logic so when you compose f.andThen(g) that essentially means g(f(x)) i.e. we first apply the function given as argument f(x) and then apply the function g to the result.
Example:
BiFunction<Integer, Integer, Integer> f = Math::addExact;
Function<Integer, Integer> g = e -> e * 2;
System.out.println(f.andThen(g).apply(10,10)); // 40
We first call function f(10, 10) and then take the result of that which is 20, pass it to the function g(20) and that is executed multiplying 20 by 2 hence yielding 40.
To be honest the syntax to call a function in Java is not the best it can be so I can understand when someone looks at this the first time it might be difficult to grasp and gets harder to follow the more you compose functions, for example in C# one could simply do g(f(10, 10)) which visibly to the eye is easier to follow, read and understand.
What's the need of this method? How does it actually fit in the
picture?
In my experience, it's not common that I've composed functions as shown above but a typical scenario I could imagine is if you have various utility methods that do some logic where the result of one function is further passed to other functions for processing in which case you can then use function composition to create various transformation pipelines by composing the utility methods.
I think the main purpose of the andThen function is to make your code more readable and more functional.
Let's look at and example:
BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
Function<Integer, Integer> negate = x -> -x;
BiFunction<Integer, Integer, Integer> newFunction = add.andThen(negate);
Guess what newFunction does? It adds andThen negates two numbers! See how similar to English this line is:
BiFunction<Integer, Integer, Integer> newFunction = add.andThen(negate);
If you call .apply(1, 2), you know you'd get -3.
Sure, you could do this without using andThen:
BiFunction<Integer, Integer, Integer> newFunction = (x, y) -> negate.apply(add.apply(x, y))
But look how unreadable that is!
Coding functionally can sometimes make things much easier to read and understand.
Consider f1.andThen(f2) :
First, f1 will take 2 elements and result in only 1
after that, f2 will take the result of f1 and tranform it to another result
BiFunction<Integer, Integer, Integer> plus10 = (i1, i2) -> i1 + i2 + 10;
Function<Integer, Integer> mult = i -> i * 5;
System.out.println(plus10.andThen(mult).apply(5, 6)); // (5+6+10) *5 = 105
It's a way to reduce computation
int val1 = plus10.apply(5, 6);
int res1 = mult.apply(val1);
int res2 = plus10.andThen(mult).apply(5, 6);
System.out.println(res1 == res2); //true
It's more and more usefull when you have several function to use, because there is the same method for Function, so you can chain them :
System.out.println(plus10.andThen(mult).andThen(mult).andThen(mult).apply(5, 6));
// (5+6+10)*5*5*5 = 2625
It's easier understood with an example:
BiFunction<Integer, Integer, String> f =
(n1, n2) -> String.format("result is %s", n1+n2);
And the "composed function" is:
BiFunction<Integer, Integer, String> f1 =
f.andThen(string -> string.toUpperCase());
Note that the second function still takes the same argument types as the first one, although it internally only needs a String to execute its logic.
Consider the invocation:
System.out.println(f1.apply(2, 3));
Which outputs RESULT IS 5, that is: it calls first function and then calls the second function with the result of the first. So it's simply understood as f1(f(x, y)) with the ultimate input being the input required by f, and the ultimate result being the result yielded by f1.
Could someone explain my the differences between methods using lambda expressions and without using it?
On the example:
Function<Double, Double> function;
public void methodCounting() {
this.function = x -> x = x + 2;
}
public double methodCounting(double x) {
x = x + 2;
return x;
}
What do we gain?
Your second method accepts a double number and returns that number + 2.
Your first method defines a Function that accepts a Double number and returns a Double whose value is the original + 2. It doesn't, however, evaluate that Function.
In order to produce the output of the second method, you could later pass a value to that Function and evaluate it :
Double d = function.apply(x); // will assign x+2 to d
would behave similarly to
double d = methodCounting(x);
Lambda is new feature added in java 8 only for optimum performance and shorter code.
Java 8 provide support for lambda expressions only with functional interfaces.
Any Interface with single abstract method is called Functional Interface.
Functional Interface is also a new feature introduced in Java 8.
lambda expressions is implicitly generate function objects in a "more convenient way" please ref. above code.
What is a first class citizen function?
Does Java supports first class citizen function?
Edit:
As mention on Wikepedia
First class functions are a necessity
for the functional programming style.
Is there any other use of first class functions?
A language that considers procedures to be "first-class" allows functions to be passed around just like any other value.
Languages like Java 7 (and earlier) and C "kind of" have this capability: C allows function pointers to be passed around, but you can't dynamically define a function in those languages and suddenly pass that somewhere else. Java before version 8 can simulate this to a certain extent with anonymous classes, but it doesn't technically have first-class functions.
On the other hand, C++, D, C#, Visual Basic .NET, Java 8+, and functional languages (like Scheme and Haskell) do allow you to pass around functions like variables. For example, the code below returns a function that adds addend to its input:
Written in D:
int delegate(int) makeAdder(int addend) //Returns a function
{
return delegate int(int x) //Long way
{
return x + addend; //Notice that addend came from _outside_ the function
};
return (int x) { return x + addend; }; //Short way
return x => addend + x; //Super-short way, introduced in D 2.058
}
Written in C#:
Func<int, int> MakeAdder(int addend) //Returns a function
{
return delegate(int x) //The long way. Note: Return type is implicitly 'int'
{
return x + addend;
};
return x => x + addend; //Short way: x "goes to" (x + addend); inferred types
}
Written in C++:
#include <functional>
std::function<int(int)> make_adder(int addend)
{
return [=](int x)
{
return addend + x;
};
}
Written in Scala:
def makeAdder(addend: Int) = (x: Int) => addend + x
Written in Python:
def make_adder(addend):
def f(x):
return addend + x
return f
# or...
return lambda x: addend + x
Written in Erlang:
make_adder(Addend) ->
fun(X) -> Addend + X end.
Written in JavaScript:
function makeAdder(addend) {
return function(x) {
return addend + x;
};
}
Written in JavaScript (ES2015 arrow function syntax):
const makeAdder = addend => x => addend + x;
Written in Scheme:
(define (makeAdder addend)
(lambda (x)
(+ x addend)))
Written in Haskell:
makeAdder :: Int -> (Int -> Int)
makeAdder addend = \x -> addend + x
Written in Visual Basic 2008:
Function MakeAdder(addend As Integer) As Func(Of Integer, Integer)
Return Function(x) (x + addend)
End Function
Written in Swift (both verbose and short-hand implementations):
func makeAdder(append: Int) -> (x: Int) -> Int {
return { (x: Int) -> Int in
return x + append
};
}
func makeAdder(append: Int) -> (Int) -> Int {
return {$0 + append};
}
(By the way, a "lambda" is just a function without a name. Lambdas are only supported in languages that support first-class functions.)
Let us consider the example of functional programming paradigm in which functions are the first class citizens. When we say functions are the first class citizens, we can do the following things with the function...
Function can be assigned to a variable
Function can be stored in a data structure
Function can be passed around as an argument to other functions
Function can be returned from the functions
In functional programming languages, it is possible to do the above mentioned things.
Now, let us try to answer the question, whether java supports first class citizen functions (or) not.
In java, methods are equivalent of functions. It is not possible to do any of the above with methods. But all of the above are possible with java objects. So, objects are the first class citizens in java. Admittedly, java8 supports passing of methods (method behavior, to be precise) to other methods using functional interfaces and lambda expressions. But that does not mean that java has functions as first class citizens.
The ability to do above things such as passing around functions, returning functions from functions is very powerful and useful. This is because, it allows us to pass around the behavior not just the data.
A first class function can be passed around. A typical example is the map function. Here is an example in Scala that squares the elements of a list:
val square = (x:Int) => x*x
val squaredList = List(1,2,3,4).map(square _)
//--> List(1,4,9,16)
The square function is here an argument to the map method, which applies it to every element. If you want to do something like this in Java, you have to use a method wrapped in a class, something like this:
interface F<A,B>{ B apply(A a); }
static <A,B> List<B> map(List<A> list, F<A,B> f) {
List<B> result = new ArrayList<B>();
for(A a:list) result.add(f.apply(a));
return result;
}
//we have to "wrap" the squaring operation in a class in order to make it a function
F<Integer,Integer> square = new F<Integer,Integer>(){
Integer apply(Integer a) { return a*a; }
}
List<Integer> ints = Arrays.<Integer>asList(1,2,3,4);
List<Integer> squares = map(ints, square);
Looking at this you can see that you can get the same task somehow done in Java, but with more overhead, and without "native" support by the language, but by using a workaround (wrapper classes). So Java doesn't support first class functions, but can "simulate" them.
Hopefully Java 8 will support first class functions. If you want to have some support for this now, look at http://functionaljava.org/ or http://functionalj.sourceforge.net/ , or have a look at the Scala language.
The Wikipedia definition is pretty good—it's a function that can be passed around like any other piece of data. Java does not support them. The closest it has is Runnable and Callable objects.
The above answers for #Alpine questions are mostly defining what is First Class Functions along with examples. But still, one question remains why to use?
I'll try to answer the benefits a little differently in Scala where first-class functions are used further as higher-order functions(map, flatMap), Partially Applied Functions and Currying:
As we focus on declarative programming, the how part of processing the data is left as an implementation detail to map, flatMap, and focused more on handling the what actual logic flow.
A caller can specify what should be done and leave the higher-order functions to handle the actual logic flow.
Partially Applied Functions and Currying: What if you wanted to reuse a function invocation and retain some of the parameters to avoid typing them in again?
Partially Applied Function Example:
def factorOf(x: Int, y: Int) = y % x == 0
val multipleOf3 = factorOf(3, _: Int)
val y = multipleOf3(78)
Currying Example:
def factorOf(x: Int)(y: Int) = y % x == 0
val isEven = factorOf(2) _
val z = isEven(32)
The above examples show you how you can reuse the part of first-class functions by not passing all parameters and keep your code DRY principle.
These are few benefits for using first-class functions
Reference for more details: https://www.oreilly.com/library/view/learning-scala
No, you cannot assign a method to a variable or pass it as an argument to another method for example.
Instead you can use interfaces to wrap the intended behaviour, or reflection to reify methods.
Functions are first class citizen means you can pass function anywhere as if it's a variable.
From Scala
def isOdd(in: Int) = in % 2 == 1
val n = (1 to 10).toList
n.filter(isOdd)
see here: isOdd is a function. passed as if it's a variale.
Objects are first class citizen in Java. A first class citizen is the one that can be passed anywhere. The parallel is from a first class citizen of country are allowed almost everywhere.
Read:
When is a feature considered a “First class citizen” in a programming language/platform?
First-class object
First-class function