Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Printing NIL as () in composites (beyond the ~:S directive)

7 views
Skip to first unread message

Blackboard Technology Group

unread,
Sep 15, 1999, 3:00:00 AM9/15/99
to
I'm looking for a standard Common Lisp solution to having NIL print as
() rather than NIL. The need stems from the use of higher
radix I/O when printing/reading aggregate structures, where NIL is
parsed as a number rather than the empty list.

This simple example illustrates the problem:

> (let ((*print-base* 36)
(*read-base* 36))
(read-from-string (prin1-to-string '(1000 (2000 ()) 3000))))
(1000 (2000 30477) 3000)

What I would have liked was a printer control, *print-nil-as-symbol*,
so I could do:

> (let ((*print-base* 36)
(*read-base* 36)
(*print-nil-as-symbol* nil))
(print (read-from-string (prin1-to-string '(1000 (2000 ()) 3000)))))
(1000 (2000 ()) 3000)
(1000 (2000 NIL) 3000)

Any suggestions? I have more complex structures than lists, so it
is more work than just writing my own recursive printer. And yes,
I do need to use the higher radix, and no, I don't have other symbols
that would also appear as valid radix integers.

The following is also not a desirable option in my situation:

> (let ((*print-base* 36)
(*print-radix* t))
(read-from-string (prin1-to-string '(1000 (2000 ()) 3000))))
(1000 (2000 NIL) 3000)

-- Dan Corkill

Kent M Pitman

unread,
Sep 15, 1999, 3:00:00 AM9/15/99
to
bbt...@rmc1.crocker.com (Blackboard Technology Group) writes:

> I'm looking for a standard Common Lisp solution to having NIL print as
> () rather than NIL.

~:S in format offers some limited control, but not recursively within
structures.

You could also just post-process the string.

I can see cases in which there is limited value to what you suggest, though
my suspicion based on extensive experience trying such hacks early in my
Lisp career is that you'd leave it accidentally turned on and would be
surprised by the number of things that would break that you never realized
depended on being able to predict how NIL prints. Just a guess.

Blackboard Technology Group

unread,
Sep 15, 1999, 3:00:00 AM9/15/99
to
In article <sfwemg0...@world.std.com>,

Kent M Pitman <pit...@world.std.com> wrote:

>> I'm looking for a standard Common Lisp solution to having NIL print as
>> () rather than NIL.

>You could also just post-process the string.

Can't do this, as the confusion already exists from the initial
printing.

>I can see cases in which there is limited value to what you suggest, though
>my suspicion based on extensive experience trying such hacks early in my
>Lisp career is that you'd leave it accidentally turned on and would be
>surprised by the number of things that would break that you never realized
>depended on being able to predict how NIL prints. Just a guess.

The standard CL reader should always be able to handle NIL represented
as (). One might imagine that any symbol printed with
*print-escape* true and an output radix high enough to cause confusion
would be printed with vertical bars, but I was seeking a less
impacting solution.

-- Dan

Blackboard Technology Group

unread,
Sep 15, 1999, 3:00:00 AM9/15/99
to
In article <7rotqk$92t$1...@rmc1.crocker.com>,

Just a comment on my comment. I went back to look at the CL definition,
and it appears that I am working with a non-compliant CL (Allegro).
The "face" example, which should print with vertical bars, does not.
Other than the extra characters over the () solution, it should be
fine on a correct implementation.

[Thanks to Kent and the HyperSpec for helping me quickly locate
the face example!!!]

-- Dan

Erik Naggum

unread,
Sep 15, 1999, 3:00:00 AM9/15/99
to
* Blackboard Technology Group

| The need stems from the use of higher radix I/O when printing/reading
| aggregate structures, where NIL is parsed as a number rather than the
| empty list.

the cause of the problem is a premature caching of the characteristics of
the symbol name when printed in a particular base: it is computed with
the prevailing value of *PRINT-BASE* when the symbol is first printed,
and retained thereafter even when that value changes. since most symbols
are first printed when the prevailing base is 10, you observe problems,
but suppose you have a package in which the symbol named FACE does not
exist, while the symbol "BEEF" does, and the value of *PRINT-BASE* and
*READ-BASE* are both the default (10). you can observe the behavior by
evaluating this snippet of code:

CL-USER(64): (let ((*print-base* 36)
(*read-base* 36))
(write (list (intern "FACE") 'beef)))
(|FACE| BEEF)
(|FACE| BEEF)

note that FACE retains its printing behavior from when it was first
printed.

to get rid of this problematic behavior, the simplest thing you can do is
to compile and load the following, which junks the caching.

(in-package :excl)
(defun get-symbol-print-flags (symbol)
(compute-symbol-name-flags (symbol-name symbol)))

this will slow your implementation down a bit, since the caching which
used to be here is quite the efficiency booster for the printer.

a better strategy, which will make the cache useful, again, is to store
the value of the base when it was computed and recompute if that base has
changed. let me know if this is important to you, performance-wise.

#:Erik

Kent M Pitman

unread,
Sep 16, 1999, 3:00:00 AM9/16/99
to
bbt...@rmc1.crocker.com (Blackboard Technology Group) writes:

> In article <sfwemg0...@world.std.com>,
> Kent M Pitman <pit...@world.std.com> wrote:
>
> >> I'm looking for a standard Common Lisp solution to having NIL print as
> >> () rather than NIL.
>
> >You could also just post-process the string.
>
> Can't do this, as the confusion already exists from the initial
> printing.
>
> >I can see cases in which there is limited value to what you suggest, though
> >my suspicion based on extensive experience trying such hacks early in my
> >Lisp career is that you'd leave it accidentally turned on and would be
> >surprised by the number of things that would break that you never realized
> >depended on being able to predict how NIL prints. Just a guess.
>

> The standard CL reader should always be able to handle NIL represented
> as (). One might imagine that any symbol printed with
> *print-escape* true and an output radix high enough to cause confusion
> would be printed with vertical bars, but I was seeking a less
> impacting solution.

You're assuming the only purpose of printing something is to use read.
I'm sure there are people that do other things. Like for example I
often do (intern (format nil "~A-FOO" symbol)) to create names of
symbols that are related to other symbols. Under your scheme, if symbol
were NIL, I'd be making a symbol called |()-FOO|. That may or may not be
what I want. (It won't necessarily break things, but it can be very ugly.)
I'm sure there are myriad other examples. Really, we played a lot with
this in the olden days.

People used to patch the Maclisp image to print NIL as () just because
they liked it better, but it broke various things. We eventually decided
it was better for it just to do something dumb and to leave "smarts" to
the pretty printer. You might try that, btw. Bind *PRINT-PRETTY* to T
and set up a special printer for type NULL.

Pierpaolo Bernardi

unread,
Sep 16, 1999, 3:00:00 AM9/16/99
to
Blackboard Technology Group (bbt...@rmc1.crocker.com) wrote:
: I'm looking for a standard Common Lisp solution to having NIL print as
: () rather than NIL. The need stems from the use of higher

: radix I/O when printing/reading aggregate structures, where NIL is
: parsed as a number rather than the empty list.

Something like the following may be what you are looking for?

(defparameter *dd* (copy-pprint-dispatch))

(set-pprint-dispatch 'null
(lambda (stream obj)
(declare (ignore obj))
(princ "()" stream))
0
*dd*)

(defun write-with-nil-as-parens (obj &rest rest)
(let ((*print-pretty* t)
(*print-pprint-dispatch* *dd*))
(apply #'write obj rest)
(values)))


==> (write-with-nil-as-parens '(nil nil))
(() ())

0 new messages