I would like to chain BiFunctions, like in the method chainWanted
in the code sample below.
BiFunction takes Function as a parameter of AndThen. is it possible to somehow chain BiFunctions ?
The code here doesn't compile because of this and I cannot cast BiFunction to Function.
import java.util.function.BiFunction;
import java.util.function.Function;
import org.openqa.selenium.remote.RemoteWebDriver;
public class Wf {
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> init = this::init;
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> wait = this::wait;
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainNow = init
.andThen(d -> {
System.out.println("--------------");
return null;
});
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainWanted = init
.andThen((BiFunction) wait);
public RemoteWebDriver init(RemoteWebDriver d, WfParams params) {
System.out.println("init(d, params)");
return d;
}
public RemoteWebDriver wait(RemoteWebDriver d, WfParams params) {
System.out.println("Wf.wait(d, params)");
return d;
}
public static void main(String[] args) throws Exception {
new Wf().start();
}
private void start() {
chainNow.apply(null, null);
}
}
Represents a function that accepts two arguments and produces a result. This is the two-arity specialization of Function . This is a functional interface whose functional method is apply(Object, Object) .
Function in Java 8A Function is a functional interface (has a single abstract method called accept) that accepts one argument and produces a result. Example: We can create a stream of integers, map each integer element to double (2x) of its value, and collect the result as a list.
The BiFunction interface consists of the following two functions: This method applies the given function to the arguments. Parameters: This method takes two parameters: Returns: This method returns the function result which is of type R. Below is the code to illustrate apply () method:
Java BiFunction methods and Examples R apply (T t, U u) – Applies this function to the given arguments and produces results. default BiFunction andThen ( Function after) – Returns a composed function that first applies this function to its input, and then applies the after function to the result. 1.1. BiFunction basic Example
The key to chaining: Pass in courseEmail as an argument to both functions, and on line 12 let courseEmail await getEmailOfCourseWithCourseId (). Result: The two following functions that we’ve passed courseEmail as an argument to will both wait until courseEmail is ready (aka the function has been run and promise has resolved), then run.
However, it is possible to cascade two or more Function objects to form a BiFunction but in that case it won’t be possible to use both the parameters at the same time. This is the utility of BiFunction.
Chaining of one Function
to another works naturally because the return value of the first function is passed as the argument to the next function, and that function's return value is passed as the argument to the subsequent function, and so forth. This doesn't work naturally with BiFunction
because they take two arguments. The first argument would be the return value from the previous function, but what would the second argument be? It also explains why BiFunction
allows chaining with andThen
to a Function
instead of to another BiFunction
.
This suggests, however, that it would be possible to chain one BiFunction
to another if there were some way of providing the value for second argument. This can be done by creating a helper function that stores the value for the second argument in a local variable. Then, a BiFunction
can be converted into a Function
by capturing that local variable from the environment and using it as the second argument.
Here's what that would look like.
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainWanted = this::chainHelper;
RemoteWebDriver chainHelper(RemoteWebDriver driver, WfParams params) {
return
init.andThen(rwd -> wait.apply(rwd, params))
.apply(driver, params);
}
// ...
chainWanted.apply(driver, params);
The chainHelper
method holds the params
argument for later capture. We call init.andThen()
in order to do the chaining. But this requires a Function
whereas wait
is a BiFunction
. Instead of using a method reference this::wait
we use the lambda expression
rwd -> wait.apply(rwd, params)
which captures params
from the lexical environment. This gives a lambda expression that takes a single argument and returns a single value, so it's now a Function
that wraps the wait
which is a BiFunction
. This is an example of partial application or currying. Finally, we call the resulting BiFunction
using apply()
, passing the original arguments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With