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)))))
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.