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.
Related
I have the following for each loop:
int someOtherVal = 0;
List<Applicators> applicatorList = List.of(applicator1, applicator2);
MyClass result = initialClassValue;
for(Applicator applicator: applicatorList) {
result = applicator.apply(result, someOtherVal);
}
The closest I can get to it using Stream API is:
applicatorList.stream()
.reduce(
initialClassValue,
(intermediateResult, applicator) -> applicator.apply(intermediateResult, someOtherVal),
(intermediateResult1, intermediateResult2) -> intermediateResult1 // complete garbage but need to provide for parallel streams which I am not using
)
Is there some other way to implement this which does not involve the needless overriding of combiner function?
My beef with using combiner function is that -
I am not using parallel streams, so combining of intermediate results should not be required
the garbage combiner override actually doesn't make sense in this context
You can do it by not specifying the initial value in the reduce method. However, this too has its disadvantages. Here is a related example:
create my own sum lambda (could have used Integer::sum)
it returns an Optional<T> of some type T.
due to the lack of an initial value it returns the first via orElse. But then, that is what your method would do if only one value. Or you could just return the optional and check if a value was present.
BinaryOperator<Integer> sumThem = (a,b)->a + b;
int[] arr = {1,2,3,4,5,6,7};
int sum = Arrays.stream(arr).boxed().reduce(sumThem::apply).orElse(1);
But there is nothing wrong with using a loop and may be the best way to go.
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;
In this question the author uses the following example:
#Override
public final OptionalInt max() {
return reduce(Math::max); //this is the gotcha line
}
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Also how would one write the javadoc for something like this?
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Not quite :). Let's start by figuring out what the reduce operator actually does. The documentation explains that it performs a reduction on a sequence of numbers by applying an algorithm that is logically equivalent to the following:
public OptionalInt reduce(IntBinaryOperator op) {
boolean foundAny = false;
int result = 0;
for (int element : [this stream]) {
if (!foundAny) {
foundAny = true;
result = element;
}
else {
result = op.applyAsInt(result, element);
}
}
return foundAny ? OptionalInt.of(result)
: OptionalInt.empty();
}
Seems simple enough. If you can tell it how to take two numbers and 'reduce' or 'combine' them into one, then reduce knows how to extend that logic to reduce an entire sequence into a single number. It handles the edge cases and the aggregation for you. All it needs from you is a function that takes in two numbers and gives it one back. That function should conform to the functional interface IntBinaryOperator.
A functional interface is an interface that is meant to describe a single function. Specifically, it describes the argument types and the return type. The rest is largely superfluous. The signature for an IntBinaryOperator looks like this:
int applyAsInt(int left, int right);
You can provide a function that conforms to this specification in several ways. Prior to Java 8, you might have done something like this:
stream.reduce(
new IntBinaryOperator() {
public int applyAsInt(int a, int b) {
return b > a ? b : a;
}
}
);
Java 8 gives us a shorthand form for functional interfaces called lambda expressions. These are a bit more concise, and while they are conceptually similar to anonymous inner classes, they're not quite the same thing.
stream.reduce((a, b) -> b > a ? b : a);
Both functions above are equivalent: they take in two numbers and return the larger of the two. As it turns out, every standard programming library has a function that does exactly the same thing. In Java, that function is Math.max. So rather than writing this logic myself, I can delegate to Math.max:
stream.reduce((a, b) -> Math.max(a, b));
But wait! All reduce wants is a function that takes two numbers and returns one. Math.max does that, so do I even need to wrap it in a lambda? It turns out I don't; I can tell reduce to just call Math.max directly:
stream.reduce(Math::max);
This says "I know you want a function, so I'm show you by name where to find one that's already been written". The compiler knows that Math.max conforms to the (int, int) -> int specification we need, so it emits some bytecode telling the VM how to 'bootstrap' it once it's needed. When the JVM hits your call to reduce, it calls a special method that generates a wrapper class implementing IntBinaryOperator that delegates to Math.max in its implementation of applyAsInt. It only performs this 'bootstrapping' step once. Since calling Math.max doesn't rely on anything other than the two numbers that get passed in, it can cache that implementation and use it the next time you wind up on this code path.
Pre Java 8, this would have been written as:
public MyMathInteface {
OptionalInt max(Integer a, Integer b);
}
public static final MyMathInterface reducing = new MyMathInterface() {
#Override
public OptionalInt max(Integer a, Integer b) {
return OptionalInt.of(Math.max(a, b));
}
};
#Override
public final OptionalInt max() {
return reduce(reducing);
}
Then reduce would be defined as:
public static OptionalInt reduce(MyMathInteface toReduce) {
return toReduce.max(someValueA, someValueB);
}
So to answer your question, no arguments are passed to Math::max, because those values are retrieved by the reduce function. They could be constants or they could be retrieved from some other place.
In any case, the use of the max method in this way is called a method reference, that is where you do SomeObject::method. That :: operator creates a method reference. It returns a function, but does not call the function. The user (reduce) is responsible for calling the function.
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