Thanks for pointing this out, and glad I remember I read it. Just ran into this 'bug'. I've a social network of agents, that can refer to each other as either steady or casual partners (recreated a model described in "Modeling Prevention Strategies for Gonorrhea and Chlamydia Using Stochastic Network Simulations"). After one of the svn revisions, looking at one of agents indeed caused a stack overflow, as two agents are referring to each other.
user=> @(world 10) #<ag...@c5575: {:born -5895, :steady nil, :inf [-100 :a], :gender :f, :sexact :lo, :casuals #{#<ag...@509bfc: {:born 5475, :steady nil, :inf [1035 :a], :gender :m, :sexact :hi, :casuals # {#<ag...@1dbe135: {:born 5475, :steady nil, :inf [2907 :a], :gender :f, :sexact :lo, :casuals #{#<ag...@509bfc: {:born 5475, :steady nil, :inf [1035 :a], :gender :m, :sexact :hi, :casuals # {#<ag...@1dbe135: (remove-method print-method clojure.lang.IDeref) works like a charm, but (binding [*print-level* 1] @(world 1)) doesn't seem to have the desired effect. Not sure why not. On Feb 10, 4:10 am, Chouser <chou...@gmail.com> wrote: > A conversation on IRC tonight[1] got me thinking... Although most > collections can be safely printed, such as at the REPL, this is not > true of all collections. Probably the best-known exception in Clojure > are infinite lazy sequences, where printing can cause an infinite > loop: > > (prn (iterate inc 0)) ; careful, you may not want to do this. > > This particular issue is addressed by the *print-level* var: > > user=> (binding [*print-length* 17] (prn (iterate inc 0))) > (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...) > nil > > Similarly, infinitely nested seqs can cause problems: > > user=> (prn ((fn x [] (lazy-cons (x) nil)))) > java.lang.StackOverflowError (NO_SOURCE_FILE:0) > > Again, there's a var for this: > > user=> (binding [*print-level* 5] (prn ((fn x [] (lazy-cons (x) nil))))) > (((((#))))) > > But now that atoms,agents, and refs print their contained value (as > of svn 1254), a new kind of infinite nesting error is possible: > > (binding [*print-level* 4] > (let [a (atom nil)] > (prn (reset! a a)))) > > This currently causes a StackOverflowError, but a patch and workaround > are available[2]: > > #<a...@1a9d1b: #<a...@1a9d1b: #<a...@1a9d1b: #<a...@1a9d1b: #>>>> > > But this is not the only possible problem with print deref'ing. > Another is that it may block on the new future objects: > > user=> (let [f (future (Thread/sleep 3000) :done)] (prn f)) > ...three second delay... > #<object$future$ide...@9c2715: :done> > > I'm not sure how much of a problem this is. One option would be > print method for future objects that doesn't deref when the future > object is not yet done: > > (.addMethod print-method (class (future)) > (fn [o w] > (.write w (format "#<fut...@%x%s>" > (System/identityHashCode o) > (if (.isDone o) > (str ": " @o) > " not done"))))) > > user=> (def f (future (Thread/sleep 3000) 777)) > #'user/f > user=> f > #<fut...@1347124 not done> > > ...wait few seconds, then... > user=> f > #<fut...@1347124: 777> > > I'm not sure if this is worth doing or not. It's certainly not the > only kind of trouble you can get into, printing objects. Any mutable > Java collection can cause a problem: > > (let [m1 (java.util.HashMap.) > m2 (java.util.HashMap. {:m1 m1})] > (.put m1 :m m2) > (prn m1)) > java.lang.StackOverflowError (NO_SOURCE_FILE:0) > > That's actually caused by HashMap's .toString method, so it's entirely > outside Clojure's control. > > --Chouser > > [1]http://clojure-log.n01se.net/date/2009-02-09.html#17:53d > [2]http://code.google.com/p/clojure/issues/detail?id=71 --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---