No *print-depth* in Clojure? How about recursive data structures?

208 views
Skip to first unread message

hiskennyness

unread,
Mar 31, 2016, 11:39:57 AM3/31/16
to Clojure
In porting my modelling library Cells to Clojure I managed to get a stack overflow when the printer tried to print a recursive data structure* I have used in the Common Lisp version.

* Basically, a ref holds a map in which some values are maps in which some values are the ref.

In Lisp we have *print-depth* as well as *print-length* to deal with just this case.

Is there some way I can deal with this, or are recursive data structures not really supported by Clojure?**

** I would consider them effectively not supported if they cannot be printed.

I'll start looking for a non-recursive solution, but I thought I would ask in case I am missing something.

thx, kt

James Reeves

unread,
Mar 31, 2016, 11:53:51 AM3/31/16
to clo...@googlegroups.com
On 31 March 2016 at 16:39, hiskennyness <kent...@gmail.com> wrote:
In porting my modelling library Cells to Clojure I managed to get a stack overflow when the printer tried to print a recursive data structure* I have used in the Common Lisp version.

* Basically, a ref holds a map in which some values are maps in which some values are the ref.

In Lisp we have *print-depth* as well as *print-length* to deal with just this case.

Is there some way I can deal with this, or are recursive data structures not really supported by Clojure?

The same variables exist in Clojure: *print-level* and *print-length* respectively.

- James

Timothy Baldridge

unread,
Mar 31, 2016, 11:56:26 AM3/31/16
to clo...@googlegroups.com
But we should mention that recursive data structures that contain refs are a bit of a code-smell. Your structures are no longer immutable if they contain refs which are mutable containers for immutable data. Something to think about.

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
“One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.”
(Robert Firth)

Kenneth Tilton

unread,
Mar 31, 2016, 12:05:10 PM3/31/16
to clo...@googlegroups.com
Doh! You can tell how often I use them. 

But this is interesting: *print-level* at the top-level is nil, but the default *behavior* seems to be limited. Same with *print-length*.

Perhaps the repl is helping out.

Thx, kt


- James

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/TGtavJVzVWk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Kenneth Tilton
Founder/Developer
TiltonTec
54 Isle of Venice Dr
Fort Lauderdale, FL 33301

@tiltonsalgebra


"In a class by itself." -Macworld


Kenneth Tilton

unread,
Mar 31, 2016, 12:28:44 PM3/31/16
to clo...@googlegroups.com
On Thu, Mar 31, 2016 at 11:56 AM, Timothy Baldridge <tbald...@gmail.com> wrote:
But we should mention that recursive data structures that contain refs are a bit of a code-smell. Your structures are no longer immutable if they contain refs which are mutable containers for immutable data. Something to think about.

I understand, but this library is all about state because it is about modelling long-lived entities over time as an unpredictable stream of events act on the model.

One good use case was a virtual RoboCup soccer team fed sensory data every 100ms and responding with actions such as turning, moving, and kicking.

So we have a long-lived soccer player instance who observes the world, forms a strategy consisting of so many tactics and emits actions based on the current tactic. New information comes in and the tactic itself has a condition that says when it has succeeded or should be abandoned. etc etc.

This is modeled with a player instance (or "model") and slots for strategy etc, each of which is a ruled cell working off the sensory data. These Cells depend on each other and notify their dependents when they change. Here comes the cycle: a Cell knows the model and slot-name it is mediating, so it is self sufficient: if someone tells me to recompute, I can do so without also being told the instance. I can then also invoke any observers, which are dispatched by slot name.

Well, this much I can change: when someone asks for my value I just need to record two pieces of information, the model and slot-name.

Of course my next problem is that no model is an island: they exist in trees where each node knows its parent (whassat? a DAG?). Hello cycle. Well, I guess just recording the model did that. Anyway, the solution that springs to mind is keeping one big dictionary keyed off a serial integer.

Thank god for 64-bits. :)

Thx, kt





You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/TGtavJVzVWk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--

Timothy Baldridge

unread,
Mar 31, 2016, 1:06:08 PM3/31/16
to clo...@googlegroups.com
>> I understand, but this library is all about state because it is about modelling long-lived entities over time as an unpredictable stream of events act on the model.

No reason why that can't be handled as a graph of nodes + a single atom. That's how you would model this in something like Loom (https://github.com/aysylu/loom), and how I model all my dataflow graphs. Start creating recursive self-referencing data structures you're in for a world of hurt. 

Kenneth Tilton

unread,
Mar 31, 2016, 5:50:09 PM3/31/16
to clo...@googlegroups.com
On Thu, Mar 31, 2016 at 1:02 PM, Timothy Baldridge <tbald...@gmail.com> wrote:
>> I understand, but this library is all about state because it is about modelling long-lived entities over time as an unpredictable stream of events act on the model.

No reason why that can't be handled as a graph of nodes + a single atom. That's how you would model this in something like Loom (https://github.com/aysylu/loom), and how I model all my dataflow graphs. Start creating recursive self-referencing data structures you're in for a world of hurt. 

<g>

I think a part of me is game for seeing if I can support concurrent updates to a cell-based universe, eg, have all eleven players update in parallel, with Clojure STM resolving conflicting updates. But thanks for the suggestion -- I have seen more than one reference to "everything in a single atom". 

I have to say, porting a hairy library like this is a great way to get up to speed on a new language. Jellz may not go anywhere, but methinks I'll be comfortable with Clojure by the time I am done.

Thanks for the input.

Cheers, Kenneth
Reply all
Reply to author
Forward
0 new messages