As discovered by cmvkk in IRC: user=> (count (reduce #(cons %2 %) [0] (range 4601))) java.lang.StackOverflowError (NO_SOURCE_FILE:0)
This is because Cons.count() is recursive via RT.count(). Presumably it's to allow efficient counting of heterogeneous seqs, like: user=> (def big-vec (into [] (range 10000000))) ; this is slow #'user/big-vec user=> (count (cons :a big-vec)) ; but this is fast 10000001 I've attached a patch that keeps this latter efficiency, but won't blow the stack for pure chains of Cons's. However, it has Cons.count() still defer to RT.count() for non-Cons rests. Since I couldn't find any other class that uses this kind of recursion for count(), it may be impossible to build a seq that would still cause Cons.count() to overflow the stack, but I'm not completely certain. An alternative, of course, would be to do a simple loop as ASeq.count() does, at the cost of the efficient vector counting demonstrated above. If you have comments or questions, don't hesitate or I'll move this to the issues page! --Chouser --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---
commit 5573feb9cdfc16533e2b27fa27013cc0b68822ba Author: Chouser <chou...@n01se.net> Date: Tue Jan 6 23:08:26 2009 -0500 Avoid stack overflow on Cons.count() diff --git a/src/jvm/clojure/lang/Cons.java b/src/jvm/clojure/lang/Cons.java index c9e65eb..c7ef54f 100644 --- a/src/jvm/clojure/lang/Cons.java +++ b/src/jvm/clojure/lang/Cons.java @@ -38,7 +38,11 @@ public ISeq rest(){ } public int count(){ - return 1 + RT.count(_rest); + int i = 1; + for(ISeq s = rest(); s != null; s = s.rest(), i++) + if( ! (s instanceof Cons) ) + return i + RT.count(s); + return i; } public ISeq seq(){