Search code examples
clojuretail-recursion

recur when mapping over a nested vector


Is my understanding of tail end optimization correct that map can't be used with tail end optimization? So if I wanted to use tail end optimization, I'd had to find a different algorithm:

(defn combinations
  "takes a vector of vectors and returns all combination with each element from each vector.
  [[1] [2 3] [4 5]] -> [[1 2 4]
                        [1 2 5]
                        [1 3 4]
                        [1 3 5]]"
  ([unprocessed]
   (combinations unprocessed [[]]))
  ([unprocessed processed]
   (if (empty? unprocessed)
     processed
     (mapcat (fn [cur]
               (mapcat (fn [prev]
                         (combinations (rest unprocessed) [(conj prev cur)]))
                       processed))
             (first unprocessed)))))

Solution

  • You are correct. And it's not about tail call optimization at all because most of the calls to combinations aren't in the tail position - even if mapcat was a language-level construct that somehow supported tail call optimization.