Matteo
Matteo

Reputation: 529

Avoid StackOverflowError in clojure with reduce

The simple code

(reduce concat (take 10000 (repeat '(1))))

causes a StackOverflowError. Suppose I have a large list of lists, like the one I obtain in this example with take. How can I merge them in one list as I tried?

Upvotes: 2

Views: 205

Answers (2)

BillRobertson42
BillRobertson42

Reputation: 12883

If (take 10000 (repeat 1)) won't work because the thing that you want to repeat already comes in a bunch seqs or lists, then you might also consider this.

(flatten (take 10000 (repeat [1])))

It seems to be more clear.

Upvotes: 0

leetwinski
leetwinski

Reputation: 17859

the problem is that concat returns a lazy seq (and stacks the function calls until the element's realization). You can fix it by realizing the concatenated collection:

(reduce (comp doall concat) (take 10000 (repeat '(1))))

but it is really slow.

in your case i would rather use something like this:

(reduce into [] (take 10000 (repeat '(1))))

it would eagerly add all the elements from every collection one by one to the resulting vector.

otherwise (if the reduce usage is not for some special extra purpose) you could just do so:

(apply concat (take 10000 (repeat '(1))))

which results to a single call of the concat, producing a lazy seq

Upvotes: 7

Related Questions