I am processing data with a variable number of functions, depending on parameters. Each of the processing functions would receive data from its predecessor, process it and pass it on to the next function.
(defn example [data]
(do-things-to data))
My application flow would be
- check parameters and store needed functions in a vector
- create a function containing all neccessary steps
- call a wrapper functions which does file management and finally applies the function
Mockup:
(let [my-big-fun (reduce comp (filter identity) vector-of-functions)]
(wrapper lots-a-arguments big-fun)
Now I figured out I need not only pass the data to the functions, but another dataset, too.
(defn new-fun-example [root data]
(do-things-to-both root data))
Is there a way to do something similar to the reduction I did to the arity-1 function? A simple juxt
won't do, as each function changes the data the next one needs. Returning a seq of '(root data)
or similars would require a great deal of rewriting in many functions.
Any ideas? I guess the answer is "macro", but I never fiddled with these...
Edit1:
The second argument is a reference to a growing graph data structure, so it doesn't need to be processed by the functions, just passed on somehow.
But the functions might originate from different namespaces, so I can't simply put the root in a higher scope to access it. A global def
would be possible, but extremely ugly...
While writing this I just thought I might map the functions to partial
somehow, before comp
ing them.
Edit2:
The filter identity
caused much confusion, it's not part of my question. I should not have included it in my sample at first place. I solved the task as suggested by the quick brown fox and apologise for being obscure at times. Minimal solution-like example:
(defn example [root data]
(swap! root + data))
(defn fn-chainer [vector-of-functions]
(let [the-root (atom 0)
; this filter step is just required to remove erroneously apperaring nils
; from the vector of functions - not part of the question
vector-of-functions (filter identity vector-of-functions)
; bake the atom to the functions
vector-of-functions (mapv #(partial % the-root) vector-of-functions)
; now chain each funcion's result as argument to the next one
my-big-fun (reduce comp vector-of-functions)]
; let the function chain process some dataset
(my-big-fun 5))
; test some function vectors
(fn-chainer [example])
=> 5 ; = 0 + 5
(fn-chainer [example example])
=> 10 ; = 0 + 5 +5
(fn-chainer [example nil example example nil nil])10
=> 20 ; = 0 + 5 + 5 + 5 + 5, nils removed