4

As a beginner in both java8 and functional programming, I think I'm missing something when reading about function composition since I cannot find a reason why there are two methods that do this, andThen and compose.

Since f.andThen(g) is exactly the same as g.compose(f), why are both needed, in which cases would using one of them be better than the other?

  • 1
    They aren't. It's just that minimality isn't the most important quality for an API. – Kilian Foth Feb 7 '17 at 10:51
  • But... there are four methods in the Function interface, minimal enough... Two of which are the named ones... So how about redundancy? – Ioanna Feb 7 '17 at 10:56
  • 5
    People who are used to mathematical functions and data flow programming find a.compose(b) easier to understand. People who are new to functionality find b.andThen(a) much easier. The Java authors think that it's more important to accomodate different users than to avoid redundancy. – Kilian Foth Feb 7 '17 at 11:01
  • 2
    Also, a colleague of mine recently argued that g.compose(f).apply(x) is closer to the mathematical, g(f(x)), whilst g.andThen(f).apply(x) is closer to... plain English :). – Ioanna Feb 7 '17 at 13:07
  • 1
    F# and some other FP languages also provide compose and flip compose operators so I don't think this is just a Java thing – jk. Feb 7 '17 at 13:37
6

compose is a traditional operation. Its order was decided by mathematicians. However, like a lot of things originally decided by mathematicians, the order isn't a very convenient convention for programmers. We include the operation anyway because functional programming has strong ties to mathematics.

In languages like Haskell, you only have the compose operator, so you have to read and write everything backwards, like:

filter even . concat . filter ((> 2) . length)

The filter for length greater than 2 happens first, then the concat, then the filter for even numbers. You get used to this, but it's still annoying, so other languages create compose operators like andThen that let you write a composed function in the order it executes. Anyone could easily add such an operator to their program in Haskell too, for that matter, it just wouldn't be idiomatic Haskell any more.

Feel free to use whichever one makes it easier for you to translate from your domain.

  • It's worth noting that one of the core Haskell modules, Control.Arrow does define an operator that does exactly this, >>>. It composes any types that are "arrows", but the definition of arrows includes standard functions. I think quite a few people use it just for this reason, and I wouldn't really describe it as " non-idiomatic ". – Jules Apr 25 '17 at 10:16
1

=v= There is also a BiFunction interface that does for two arguments what Function does for one. This interface has no compose because that won't work on two arguments, but it does have andThen. So one advantage of Function#andThen is consistency with BiFunction.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.