PianoMastR64
PianoMastR64

Reputation: 417

What would a compose method in the BiFunction interface look like?

The Function interface has the compose() and andThen() methods while the BiFunction interface only has the andThen() method. My question is simply how could the corresponding method be implemented? I'll try to represent this graphically.

BiFunction without compose

The single letters are parameterized types as defined by Java's Function and BiFunction interfaces. Arrows are the flow of inputs and outputs. Boxes with connected arrows are functions. The dotted box just shows how the apply method is used.

Upvotes: 2

Views: 312

Answers (1)

PianoMastR64
PianoMastR64

Reputation: 417

The Function's Compose() and andThen() methods are straightforward since a Function has one input and one output and therefore can only be strung sequentially with another in two ways.

Since a BiFunction has one output, the "after" function has to be something with only one corresponding input, and Function fits the bill. And since it has two inputs, the "before" function needs to be something with two outputs? You can't have a method return two things, so there seemingly can't be a "before". The return type of each of these methods is the same as the interface they are defined in, so the proposed method should return a BiFunction.

My proposal then is a method that takes two Functions as input and returns a BiFunction. I'm not sure what else it could even be. It couldn't be two BiFunctions because then the return type would have to be a QuaterFunction.

Here is the code as it would be written in the Java Library:

public interface BiFunction<T, U, R> {
    // apply()...

    default <V, W> BiFunction<V, W, R> compose(
        Function<? super V, ? extends T> beforeLeft,
        Function<? super W, ? extends U> beforeRight) {
        
        Objects.requireNonNull(beforeLeft);
        Objects.requireNonNull(beforeRight);
        return (V v, W w) -> apply(beforeLeft.apply(v), beforeRight.apply(w));
    }

    // andThen()...
}

Here is the finished graph:

enter image description here

Here it is in use:

BiFunction<Integer, Integer, Integer> add = Integer::sum;
Function<Integer, Integer> abs = Math::abs;
BiFunction<Integer, Integer, Integer> addAbs = add.compose(abs, abs);
System.out.println(addAbs.apply(-2, -3));

// output: 5

If you want to actually test this, you can do something like this:

public interface BiFunctionWithCompose<T, U, R> extends BiFunction<T, U, R> {...

Or like this:

package myutil;
public interface BiFunction<T, U, R> extends java.util.function.BiFunction<T, U, R> {...

I have no idea if this will be useful to anyone, but it was really fun to think through and write. Have a wonderful day.

Upvotes: 2

Related Questions