From: Blackboard Technology Group
Subject: Printing NIL as () in composites (beyond the ~:S directive)
Date: 
Message-ID: <7ro9uo$3uo$1@rmc1.crocker.com>
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

From: Erik Naggum
Subject: Re: Printing NIL as () in composites (beyond the ~:S directive)
Date: 
Message-ID: <3146421171283688@naggum.no>
* 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
From: Kent M Pitman
Subject: Re: Printing NIL as () in composites (beyond the ~:S directive)
Date: 
Message-ID: <sfwemg0vz23.fsf@world.std.com>
······@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.
From: Blackboard Technology Group
Subject: Re: Printing NIL as () in composites (beyond the ~:S directive)
Date: 
Message-ID: <7rotqk$92t$1@rmc1.crocker.com>
In article <···············@world.std.com>,
Kent M Pitman  <······@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
From: Blackboard Technology Group
Subject: Re: Printing NIL as () in composites (beyond the ~:S directive)
Date: 
Message-ID: <7roupn$c1h$1@rmc1.crocker.com>
In article <············@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

>
>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
>
>
From: Kent M Pitman
Subject: Re: Printing NIL as () in composites (beyond the ~:S directive)
Date: 
Message-ID: <sfwpuzj5w9e.fsf@world.std.com>
······@rmc1.crocker.com (Blackboard Technology Group) writes:

> In article <···············@world.std.com>,
> Kent M Pitman  <······@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.
From: Pierpaolo Bernardi
Subject: Re: Printing NIL as () in composites (beyond the ~:S directive)
Date: 
Message-ID: <937499806.253075@fire-int>
Blackboard Technology Group (······@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))
(() ())