如何链接BiFunctions?

Pan*_*lak 10 java functional-programming java-8

我想链接BiFunctions,就像chainWanted下面的代码示例中的方法一样.

BiFunction将Function作为AndThen的参数.有可能以某种方式链接BiFunctions?

这里的代码因为这个而无法编译,我无法将BiFunction转换为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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Stu*_*rks 6

将一个链接Function到另一个的工作自然是因为第一个函数的返回值作为参数传递给下一个函数,并且该函数的返回值作为参数传递给后续函数,依此类推.这不自然地起作用,BiFunction因为它们有两个参数.第一个参数是前一个函数的返回值,但第二个参数是什么?它还解释了为什么BiFunction允许链接andThen到一个Function而不是另一个BiFunction.

然而,这表明BiFunction如果有某种方式为第二个参数提供价值,就可以将一个链接到另一个.这可以通过创建一个辅助函数来完成,该函数将第二个参数的值存储在局部变量中.然后,BiFunction可以Function通过从环境中捕获该局部变量并将其用作第二个参数来将a转换为a .

这就是看起来的样子.

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);
Run Code Online (Sandbox Code Playgroud)

chainHelper方法保留了params以后捕获的参数.我们打电话init.andThen()来做链接.但这需要一个Functionwait不是BiFunction.this::wait我们使用lambda表达式而不是使用方法引用

rwd -> wait.apply(rwd, params)
Run Code Online (Sandbox Code Playgroud)

params从词汇环境中捕获.这给出了一个lambda表达式,它接受一个参数并返回一个值,所以它现在是一个Function包装wait它是一个BiFunction.这是部分应用currying的一个例子.最后,我们调用结果BiFunction使用apply(),传递原始参数.


Mis*_*sha 0

调用时 WfParams 应该从哪里来wait?如果您打算为所有函数调用重用相同的 WfParams,只需将 WfParams 作为类成员变量,而不是将其传递给每个函数。

class Wf {
    private final WfParams params;

    public Wf(WfParams params) {
        this.params = params;
    }

    UnaryOperator<RemoteWebDriver> init = this::init;
    UnaryOperator<RemoteWebDriver> wait = this::wait;

    Function<RemoteWebDriver,RemoteWebDriver> chain = init.andThen(wait);

    RemoteWebDriver init(RemoteWebDriver d) {
        // can use WfParams here
        return d;
    }

    RemoteWebDriver wait(RemoteWebDriver d) {
        // can use WfParams here            
        return d;
    }

    private void start() {
        chain.apply(null);
    }

    public static void main(String[] args) {
        new Wf(new WfParams()).start();
    }   
}
Run Code Online (Sandbox Code Playgroud)

您想使用这样的函数链有什么特殊原因吗?为什么不简单地init(...); wait(...);从调用start()