Home > Back-end >  Why can't I compose two different functions with identical parameter types?
Why can't I compose two different functions with identical parameter types?

Time:12-21

I have the following code:

        Function<String,Integer> f1=s->Integer.valueOf(s) 1;
        Function<String,Integer> f2=s->Integer.valueOf(s)*2;
        Function<String,Integer> f3=f1.compose(f2);

And this is the error I am getting:

method compose in interface Function<T,R> cannot be applied to given types;

What is wrong with this code?

I then looked at the compose() in the documentation:

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
    }

I could not fully understand it. Someone, to explain to me the relationship between the parameters of the functions that can be composed?

CodePudding user response:

To compose two functions means that the result of one will be the input to the other. Therefore, if you have two functions that have the same input type as each other and the same output type as each other but the input and output types differ, then they are not composable in either order.

In your particular case, you are requesting a composed function that applies f1() to the result of f2(), but the result of f2() is an Integer, whereas f1() requires an input of type String. One way to approach the problem would be to modify f1() so that it operates on Integers:

        Function<Integer, Integer> f1 = i -> i   1;
        Function<String, Integer> f2 = s -> Integer.valueOf(s) * 2;
        Function<String, Integer> f3 = f1.compose(f2);

If you cannot modify f1(), then you could insert an intermediate conversion back to String into your composition chain:

        Function<String, Integer> f1=s->Integer.valueOf(s) 1;
        Function<String, Integer> f2 = s -> Integer.valueOf(s) * 2;
        Function<String, Integer> f3 = f1.compose(f2.andThen(Integer::toString));

But of course, all those conversion back and forth to String are expensive.

CodePudding user response:

Function compose 'chains' functions, and function itself has a result type. Your function with a different input type and output type cannot be 'reused' in the same function of course. See compose as doing the function in order: first step: string in f2, output is integer. Then output of f2 in f1 however has as input a string, not an integer. Hence your function compose will not work. You can only chain a function if the output of the first function can be used as input of the second function:

        Function<Integer, Integer> f1 = i -> i   1;
        Function<String, Integer> f2 = s -> Integer.valueOf(s) * 2;
        Function<String, Integer> f3 = f1.compose(f2);
  • Related