In F# if I write
let p = printfn "something"
it will evaluate the expression once. Any subsequent references to p
will evaluate to unit.
From a theoretical perspective, the definition of a function, this makes sense. A function should only return the same result for the same input.
However if I want the side-effect to occur (i.e. the output to the screen), then I need the pass an argument to p. Typically this argument is the unit
value.
let p () = printfn "something"
But why will F# evaluate the function each time, when the argument is the same each time the function is applied? Surely the same reasoning should apply as in the first case? The input to the function p
doesn't change therefore there is no need to evaluate it more than once.
The action printfn
is, strictly speaking, not a function. It is, particularly, not a pure function, because it's not referentially transparent. This is possible because F# isn't a strictly functional language (it's a 'functional first' language). It makes no explicit distinction between pure functions and impure actions.
The return value of printfn "something"
is ()
(unit
), which means that p
is bound to the unit value ()
. The fact that something
is printed on the screen is a side effect of evaluating the expression.
F# is an eagerly evaluated language. That's why you see something
printed on the screen as a side effect of binding printfn "something"
to p
. Once the expression is evaluated, p
is only bound to ()
- the value.
F# doesn't memoize function calls, so when you change p
to a function, it'll evaluate the function every time you call it with ()
. Since all functions can be impure, the compiler can't tell whether or not memoization would be appropriate, so it doesn't do that.
Other languages do this in different ways. Haskell, for example, is lazily evaluated, and also explicitly distinguishes between pure functions and impure actions, so it can apply different optimization in cases like these.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With