…Maybe imperative programming with mutable data is just drilled too deep into my brain, but I find the code for building up vectors of data in Clojure to be verbose, unwieldy, and convoluted. There must be a better way!
In Ruby I might write code like:
results = []
a_collection.each do |x|
x.nested_collection.each do |y|
next if some_condition_holds
results << y
end
end
In Clojure, I don’t know of a better way to do that than to use a recursive function, perhaps like the following (horrendous) code:
; NEWBIE ALERT! NEWBIE ALERT!
(loop [results []
remaining a_collection]
(if (empty? remaining)
results
(recur
(loop [results results
nested (nested_collection (first remaining))]
(if (empty? nested)
results
(if (some_condition_holds)
(recur results (rest nested))
(recur (conj results (first nested)) (rest nested)))))
(rest remaining))))
Without mutable data and iterative loops, you need to use recursion to build up a collection. Each such recursive function needs an (empty?) guard clause, etc. etc. The whole thing is so repetitive it makes me want to scream.
In simple cases, map would be enough, but I’m thinking of cases where there are multiple levels of nesting, and at each level, there may be conditions which require skipping an iteration.
In Common Lisp I might use the loop macro, or mapcan. Doesn’t Clojure have anything like mapcan?
In descending order of how nice I think the options look:
Alternatively, if you’d rather build it out of functions like
mapandmapcatinstead of using theforsyntax:If you are really keen on it, you can also build it with partial function applications and composition:
This third style doesn’t read very well in Clojure, although equivalent code in some other languages is very nice. In Haskell, for example: