Patch available: *print-length*, *print-level*

15 views
Skip to first unread message

Stephen C. Gilardi

unread,
Oct 24, 2008, 2:55:13 AM10/24/08
to Clojure
Rich mentioned on #clojure that a patch to implement *print-length* would be welcome.

I've uploaded a patch that implements Common Lisp's *print-length* and *print-level* for Clojure:


The CL docs are at:


*print-length* can be especially useful in Clojure's repl to avoid accidentally printing an infinite seq and having to abort your session.

I've enclosed an example and docs below.

Notes:
- I changed the print method for vector to use print-sequential. It didn't seem essential to avoid print-sequential and it allowed me to implement *print-length* and *print-level* in one place where it's intended to be effective for all collections.
- I was surprised to find what appears to be an error in the Common Lisp Hyperspec. The output for length = 5 in the example for *print-length* gives the desired out as (1 2 3 4 5 6). My reading of the docs and tests I ran with CLISP and sbcl all indicate the output should be (1 2 3 4 5 ...). I implemented the latter.
- We have no dotted lists in Clojure so the special case for *print-length* with a dotted list doesn't apply.
- I added these variables to the group whose bindings are pushed and popped in Repl.java so that we can use set! to set them in the repl.

--Steve


Clojure
user=> (set! *print-length* 100)
100
user=> (iterate inc 1)
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 ...)
user=> (doc *print-length*)
-------------------------
clojure/*print-length*
nil
  *print-length* controls how many items of each collection the
  printer will print. If it is bound to logical false, there is no
  limit. Otherwise, it must be bound to an integer indicating the maximum
  number of items of each collection to print. If a collection contains
  more items, the printer will print items up to the limit followed by
  '...' to represent the remaining items. The root binding is nil
  indicating no limit.
nil
user=> (doc *print-level*)
-------------------------
clojure/*print-level*
nil
  *print-level* controls how many levels deep the printer will
  print nested objects. If it is bound to logical false, there is no
  limit. Otherwise, it must be bound to an integer indicating the maximum
  level to print. Each argument to print is at level 0; if an argument is a
  collection, its items are at level 1; and so on. If an object is a
  collection and is at a level greater than or equal to the value bound to
  *print-level*, the printer prints '#' to represent it. The root binding
  is nil indicating no limit.
nil
user=> 

Rich Hickey

unread,
Oct 24, 2008, 7:53:54 AM10/24/08
to Clojure


On Oct 24, 2:55 am, "Stephen C. Gilardi" <squee...@mac.com> wrote:
> Rich mentioned on #clojure that a patch to implement *print-length*
> would be welcome.
>
> I've uploaded a patch that implements Common Lisp's *print-length* and
> *print-level* for Clojure:
>
> http://clojure.googlegroups.com/web/print-length-level.patch
>
> The CL docs are at:
>
> http://www.lispworks.com/documentation/HyperSpec/Body/v_pr_lev.htm
>
> *print-length* can be especially useful in Clojure's repl to avoid
> accidentally printing an infinite seq and having to abort your session.
>
> I've enclosed an example and docs below.
>

Awesome - thanks!

Patch applied (SVN 1077)

Rich

Stuart Sierra

unread,
Oct 24, 2008, 12:18:44 PM10/24/08
to clo...@googlegroups.com
On Oct 24, 2:55 am, "Stephen C. Gilardi" <squee...@mac.com> wrote:
> I've uploaded a patch that implements Common Lisp's *print-length* and
> *print-level* for Clojure:

Really nice. Thanks, Stephen! Could the *print-level* cutoff
indicator be something more visible than '#'? Maybe '#=(...)' or
something.

I've attached a patch to add *print-str-length* that does the same
thing for strings:

user=> (set! *print-str-length* 30)
30
user=> (slurp "bigfile.xml")
"<?xml version=\"1.0\" encoding=\"..."
user=> (count *1)
2540

I feel like these variables should be named '*pr-level*' and so on,
since they affect 'pr' and 'pr-str' but not 'print'.

-Stuart Sierra

Stuart Sierra

unread,
Oct 24, 2008, 12:26:25 PM10/24/08
to clo...@googlegroups.com
On Oct 24, 12:18 pm, "Stuart Sierra" <the.stuart.sie...@gmail.com> wrote:
> I've attached a patch to add *print-str-length* that does the same
> thing for strings:

Okay, NOW I've attached a patch.
-Stuart

pr-str-length.patch

Stephen C. Gilardi

unread,
Oct 24, 2008, 1:16:24 PM10/24/08
to clo...@googlegroups.com
On Oct 24, 2008, at 12:18 PM, Stuart Sierra wrote:

On Oct 24, 2:55 am, "Stephen C. Gilardi" <squee...@mac.com> wrote:
I've uploaded a patch that implements Common Lisp's *print-length* and
*print-level* for Clojure:

Really nice.  Thanks, Stephen!

Thanks! :-)

Could the *print-level* cutoff
indicator be something more visible than '#'?  Maybe '#=(...)' or
something.

I went with Common Lisp precedent. Thinking about it further, it seems it would be nice to use something that's guaranteed unreadable.  As it is now, it will be a \# followed by a collection-dependent separator or by a collection-dependent "end" character (like \) or \] or \}). Perhaps it would be better to print a known, fixed dispatch character right after the \# so that the entire thing is guaranteed unreadable. Do we have a dispatch character reserved for that already?

I've attached a patch to add *print-str-length* that does the same
thing for strings:

user=> (set! *print-str-length* 30)
30
user=> (slurp "bigfile.xml")
"<?xml version=\"1.0\" encoding=\"..."
user=> (count *1)
2540

Neat. I like it.

I feel like these variables should be named '*pr-level*' and so on,
since they affect 'pr' and 'pr-str' but not 'print'.

*print-length* and *print-level* do affect print and println as well as pr and prn and pr-str.

--Steve

Stuart Sierra

unread,
Oct 24, 2008, 1:37:01 PM10/24/08
to Clojure
On Oct 24, 1:16 pm, "Stephen C. Gilardi" <squee...@mac.com> wrote:
> *print-length* and *print-level* do affect print and println as well  
> as pr and prn and pr-str.

Ah, my mistake. Never mind, then.
-Stuart
Reply all
Reply to author
Forward
0 new messages