Fork me on GitHub
#beginners
<
2015-08-22
>
gabehollombe10:08:51

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

gabehollombe10:08:55

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

gabehollombe11:08:14

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?

agile_geek12:08:22

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.

potetm13:08:41

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

gabehollombe13:08:27

thanks a ton for that very clear explanation @alexmiller

gabehollombe13:08:55

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: http://clojurian.blogspot.sg/2012/11/beware-of-mapcat.html which provides a different version of mapcat that purports to use less memory 😃

bmay15:08:23

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

bmay15:08:35

ah okay, thanks

bmay16:08:56

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

bmay16:08:14

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 https://clojuredocs.org/clojure.core/memfn

frank19:08:49

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

frank19:08:07

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