Originally, this blogpost was titled “Use apply and carry on”, but I guess naming the function
apply after Kotlin (damn you, Kotlin!) wasn’t the most preferred option by the public. I did like
apple |> apply eat semantics but if Scott Wlaschin says
apply is a different thing then it is a different thing. To be precise Scott’s is
apply: (a -> b) -> a -> b and mine was (emphasize on was)
apply: (a -> unit) -> a -> a. Apparently, the function which does whatever I wanted
apply to do is called
tee (after Unix command) or
tap (at least in Ruby and Ramda.js).
So I’ve edited it and replaced
tee, but essentially it is almost unchanged… Let’s go then.
One of everyone’s favourite features of F# is pipe (
|>) operator. It allows to pipe output of one function as input to another function preserving visual honesty. The general idea is that, in English, we read left-to-right and top-down. In C# (C, C++, Java, Pascal, Python) we read in all possible directions, most likely top-down for overall structure but botton-up and right-to-left for single statements.
starts at the right end going left-to-right for a moment (
x*5.2 + 7.1) but then turns right-to-left with
Math.Exp and finally
Math.Round (in this order). In F# the pipe operator (
|>) allows to write code exactly in the same order as it is going to be executed:
Around the world, many hours have been spent arranging function arguments (guilty!) to allow such seamless experience. But sometimes, the universe is against us. Let’s assume we would like to print out the value after
Math.Sin. The conservative approach would be quite intrusive - we would need to break expression in half:
Whoa! That is intrusive.
But here comes the rescue. The
tee function implemented as:
The function itself is trivial, it takes a function and an argument, executes given function with given argument but then returns it, so the argument goes through the function:
In the example above, the value passed between
Math.Exp has been redirected “for a moment” to
printf "%g" without any temporary variables or breaking the flow.
Recently I needed to shuffle an array. The algorithm I used shuffles array in place:
Random.randomInt is not a standard function, but its implementation is irrelevant for this example)
I needed it as pure function, which will not mutate input array, just return shuffled version of it. Let’s do it:
Maybe we can do better with
tee? Yes, we can:
So, use tee and carry on!