Reputation:
I'm looking for something that is probably very well defined in Clojure (in the Lisp world at large in fact) but I don't have enough experience or culture to get on the right track and Google hasn't been very helpful so far.
Let's say I have three simple forms:
(defn add-one [v] (+ v 1))
(defn add-two [v] (+ v 2))
(defn add-three [v] (+ v 3))
Out of convenience, they are stored in a vector. In the real world, that vector would vary depending on the context:
(def operations
[add-one
add-two
add-three])
And I also have an initial value:
(def value 42)
Now, I would like to apply all the functions in that vector to that value and get the result of the combined operations:
(loop [ops operations
val value]
(if (empty? ops)
val
(recur (rest ops)
((first ops) val))))
While this does work, I'm surprised there isn't a higher level form just for that. I've looked all over the place but couldn't find anything.
Upvotes: 2
Views: 760
Reputation: 13483
The functional phrase you are searching for is (apply comp operations)
:
((apply comp operations) 42)
;48
Your loop does work if you feed it 42
for value
:
(loop [ops operations
val 42]
(if (empty? ops)
val
(recur (rest ops)
((first ops) val))))
;48
This applies the operations in the opposite order from comp
.
... As does using reduce
:
(reduce (fn [v f] (f v)) 42 operations)
;48
If you look at the source code for comp
, you'll find that the general case essentially executes a loop
similar to yours upon a reverse
d list of the supplied functions.
Upvotes: 8
Reputation: 7599
'In Lisp world at large' you can use reduce
:
user> (reduce (fn [x y] (y x)) 5 [inc inc inc inc])
;; => 9
This may look not so sexy, but it works everywhere with minor variations (this is Common Lisp, for example):
CL-USER> (reduce (lambda (x y) (funcall y x))
'(1+ 1+ 1+ 1+)
:initial-value 5)
9
Upvotes: 1