Clojure has a macro, ->
, which takes a piece of data and a bunch of functions, applies the data to the first function, and then applies the result of that to the next one, the result of that to the third one, and so on, finally giving you back the result of the last application.
I quite like this because instead of having to write functions backwards from the order in which they are applied, like so: (pseudo-code follows)
floor (square.root (x))
you can write them in the order that the data flows through them:
-> x (square.root, floor)
My question is, is there a standard name for this function in functional languages, in the way that map, reduce, and filter have standard names? The Clojure docs describe it as 'threading the data through the functions', but I couldn't find anything on googling the word thread
. I wrote a simple version of it in Haskell:
thread :: a -> [(a -> a)] -> a
thread x [] = x
thread x (f:fs) = thread (f x) fs
and searched for a -> [(a -> a)] -> a
on Hoogle, but that didn't come up with anything either.
While researching for this question I also gleaned that you can do a very similar thing using the function composition operators from Control.Arrow
in Haskell, like so:
($2) (sin >>> cos >>> tan)
whereas using the dedicated higher-order thread
function you would write:
thread 2 [sin, cos, tan]
Is it perhaps the case that the first formulation suffices for practical usage?
The name you're looking for is function composition.
The difference between the threading macro and comp
comes from the former leveraging Clojure homoiconicity, while the latter is more close to the mathematical definition of composition.
In facts, you can transform a threading macro call to a comp
call if you create one function of one argument per step, and reverse the order of the functions:
(defn sin [n] (Math/sin n))
(defn cos [n] (Math/cos n))
(-> 1 sin cos sin cos cos) ; 0.6858966217219662
((comp cos cos sin cos sin) 1) ; 0.6858966217219662
I think you can use foldl
for this, using appropriate arguments:
-- functions for testing
f1 x = x+1
f2 x = x*2
f3 x = x*x
-- here comes the line you're interested in
foldl (\x y -> y x) 2 [f1, f2, f3]
The arguments are as follows:
(\x y -> y x)
is a function taking a function y
and applying it to the argument x
. y
will then be substituted by each function from the list.2
is the initial argument you want to give to the functions.[f1, f2, f3]
is the list of functions.Using these arguments, foldl
computes the following: f3(f2(f1(2)))
.
Given that >>>
is similar to bash shell's pipeline operator rooted from Unix, I would call it pipeline sequence combinator.
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