17

I’m taking my first baby-steps in learning functional programing using F# and I’ve just come across the Forward Pipe (|>) and Forward Composition (>>) operators. At first I thought they were just sugar rather than having an effect on the final running code (though I know piping helps with type inference).

However I came across this SO article: What are advantages and disadvantages of “point free” style in functional programming? Which has two interesting and informative answers (that instead of simplifying things for me opened a whole can of worms surrounding “point-free” or “pointless” style) My take-home from these (and other reading around) is that point-free is a debated area. Like lambas, point-free style can make code easier to understand, or much harder, depending on use. It can help in naming things meaningfully.

But my question concerns a comment on the first answer: AshleyF muses in the answer:

“It seems to me that composition may reduce GC pressure by making it more obvious to the compiler that there is no need to produce intermediate values as in pipelining; helping make the so-called "deforestation" problem more tractable.”

Gasche replies:

“The part about improved compilation is not true at all. In most languages, point-free style will actually decrease performances. Haskell relies heavily on optimizations precisely because it's the only way to make the cost of these things bearable. At best, those combinators are inlined away and you get an equivalent pointful version”

Can anyone expand on the performance implications? (In general and specifically for F#) I had just assumed it was a writing-style thing and the compiler would unstrangle both idioms into equivalent code.

Community
  • 1
  • 1
Stoatly
  • 171
  • 4
  • 2
    If there is a performance difference one way or the other, I'm quite sure it will be very small in most cases. So, you shouldn't worry about this unless you are writing performance-critical part of your code. – svick Jul 25 '12 at 12:55
  • 3
    As an aside, `(|>)` isn't really related to point free programming (it just allows a function's argument to be placed before the function itself syntactically), and should be inlined, so there should be no performance impact. – kvb Jul 25 '12 at 13:14
  • @kvb that was sort of the impression I'd formed about |> , (my question was originally even longer and more rambling - I was going to ask for more clarification about point-freeness, but I reckon I should do a bit more reading around for myself as there is a lot already out there on it) – Stoatly Jul 25 '12 at 18:39

1 Answers1

35

This answer is going to be F#-specific. I don't know how the internals of other functional languages work, and the fact that they don't compile to CIL could make a big difference.

I can see three questions here:

  1. What are the performance implications of using |>?
  2. What are the performance implications of using >>?
  3. What is the performance difference between declaring a function with its arguments and without them?

The answers (using examples from the question you linked to):

  1. Is there any difference between x |> sqr |> sum and sum (sqr x)?

    No, there isn't. The compiled CIL is exactly the same (here represented in C#):

    sum.Invoke(sqr.Invoke(x))
    

    (Invoke() is used, because sqr and sum are not CIL methods, they are FSharpFunc, but that's not relevant here.)

  2. Is there any difference between (sqr >> sum) x and sum (sqr x)?

    No, both samples compile to the same CIL as above.

  3. Is there any difference between let sumsqr = sqr >> sum and let sumsqr x = (sqr >> sum) x?

    Yes, the compiled code is different. If you specify the argument, sumsqr is compiled into a normal CLI method. But if you don't specify it, it's compiled as a property of type FSharpFunc with a backing field, whose Invoke() method contains the code.

    But the effect of all is that invoking the point-free version means loading one field (the FSharpFunc), which is not done if you specify the argument. But I think that shouldn't measurably affect performance, except in the most extreme circumstances.

Community
  • 1
  • 1
svick
  • 236,525
  • 50
  • 385
  • 514