;; notice that it is better to use a back quote, to qoute function names for macro, as it fully qualifies them.
;; and so on
(defmacro with-middleware [routes]
`(-> ~routes ~@middleware))
The main point of -> is to make code easier to read. But if one writes a new macro solely in order to use -> (in code nobody will ever see because it exists only at macro-expansion), it seems to me that this is doing a lot of work for no benefit. Moreover, I believe it obscures, rather than clarifies, the code.
So, in the spirit of never using a macro where functions will do, I suggest the following two equivalent solutions:
(reduce #(%2 %) routes middleware)
((apply comp middleware) routes)
A Better Way
The second solution is easily simplified by changing the definition of middleware from being a list of the functions to being the composition of the functions:
;; and so on
When I began learning Clojure, I ran across this pattern often enough that many of my early projects have an freduce defined in core:
"Given an initial input and a collection of functions (f1,..,fn),
This is logically equivalent to ((comp fn ... f1) input)."
(reduce #(%2 %) in fs))
This is totally unnecessary, and some might prefer the direct use of reduce as being more clear. However, if you don't like staring at #(%2 %) in your application code, adding another utility word to your language is fine.
Asked in February 2016Viewed 2,023 timesVoted 14Answered 2 times