Binding one Function to another works naturally, because the return value of the first function is passed as an argument to the next function, and this return value of the function is passed as an argument to the next function, etc. This does not work naturally with BiFunction because they accept two arguments. The first argument will be the return value from the previous function, but what will be the second argument? This also explains why BiFunction allows BiFunction to bind with andThen to Function instead of another BiFunction .
This suggests that one BiFunction could be associated with another if there was some way to provide a value for the 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 to Function by capturing this local variable from the environment and using it as the second argument.
Here is how it will look.
BiFunction<RemoteWebDriver, WfParams, RemoteWebDriver> chainWanted = this::chainHelper; RemoteWebDriver chainHelper(RemoteWebDriver driver, WfParams params) { return init.andThen(rwd -> wait.apply(rwd, params)) .apply(driver, params); }
The chainHelper method contains the params argument for subsequent capture. We will call init.andThen() to execute the chain. But this requires Function , while wait is a BiFunction . Instead of using the this::wait method reference, we use a lambda expression
rwd -> wait.apply(rwd, params)
which captures params from the lexical environment. This gives a lambda expression that takes one argument and returns a single value, so now it's a Function that wraps wait , which is a BiFunction . This is an example of partial use or currying. Finally, we call the resulting BiFunction using apply() , passing the original arguments.
source share