Fork me on GitHub

Could someone explain how this implementation of flatten using mapcat works? (looking at answers from 4clojure)


(fn flatten* [x]
  (if (coll? x)
    (mapcat flatten* x)


ooh, I think I may get it now (after some thinking). Does it just recur on each element in x, putting it into its own vector if it’s not a collection, and then concatenate all of those single element vectors?


I was drawing same conclusion. So it walks down tree of nested collections creating single vectors for the contents I think?

Alex Miller (Clojure team)13:08:58

At every node if it's a collection (a branch) it applies itself recursively and concatenates the results. If it's not a collection (a leaf), it's made into a collection so that the parent branch will be able to apply flatten* to it.


I think you both have the right idea, but in my own words, you have a function that returns a flattened list of the elements you gave it. When the “elements you gave it” is a single item, then a flattened list is obviously [element]. If the element is a collection, you need to concatenate the flattened lists of the elements in the collection.

Alex Miller (Clojure team)13:08:04

Which is clever, however it's also recursive which means the depth of the tree has to fit on the stack

Alex Miller (Clojure team)13:08:50

So not very big trees would give you a stackoverflow

Alex Miller (Clojure team)13:08:54

As opposed to the something that walked the tree in order and accumulated the flattened result


thanks a ton for that very clear explanation @alexmiller


I just did a quick search to read up more on mapcat and how it differs from the accumulated alternative you mention, and I found this: which provides a different version of mapcat that purports to use less memory 😃


is it possible to use the thread-first macro with interop functions?

Alex Miller (Clojure team)15:08:28

Only if you wrap it in an anon fn

Alex Miller (Clojure team)15:08:49

But there is .. For chained interop


ah okay, thanks


hmm trying to find a way to use filter with a java interop predicate in a thread-first macro


there has to be a way other than creating a new function

Alex Miller (Clojure team)18:08:24

there's also memfn although I can't say I ever see people use it


is there a way I can wrap a compojure handler with another compojure handler


i'd like the (route/resources "/") to respond without going any further up the middleware stack