Subject: princ & *print-readably*

From: Sam Steingold <[email-masked]>
Date: 24 Mar 1998 13:07:42 -0500

The following message is a courtesy copy of an article
that has been posted to comp.lang.lisp as well.

what should (let ((*print-readably* t)) (princ "zz"))
print? "zz" or zz?
ACL says zz, CMU says "zz", and CLISP said "zz" untill the today's patch
wich changed this to zz. Who is right?

$ clisp
> (setq *print-readably* t)
T
> (princ "zzz")
"zzz"
"zzz"
Bye.
$ lisp
Validating memory ... done.
Mapping 8261632 bytes at 0x1000000.
Mapping 13979648 bytes at 0x5000000.
CMU Common Lisp 18a x86-linux 1.4.0 cvs, running on mute.eaglets.com
Send bug reports and questions to your local CMU CL maintainer, 
or to [email-masked],
or to [email-masked] or [email-masked]
or to [email-masked]. (prefered)

type (help) for help, (quit) to exit, and (demo) to see the demos

Loaded subsystems:
    Python 1.0, target Intel x86
    CLOS based on PCL version:  September 16 92 PCL (f)
    CLX X Library MIT R5.02
    Lisp-Tk 0.1
    Clio Library 1
    Defsystem Mar 13 1995
* (setq *print-readably* t)

T
"* "(princ "zzz")
"zzz"
"zzz"
"* "(quit)
$ acl
Allegro CL 4.3 [Linux/X86; R1] (12/11/96 1:33)
Copyright (C) 1985-1996, Franz Inc., Berkeley, CA, USA.  All Rights Reserved.
;; Optimization settings: safety 1, space 1, speed 1, debug 2.
;; For a complete description of all compiler switches given the current
;; optimization settings evaluate (explain-compiler-settings).
USER(1): (setq *print-readably* t)
T
USER(2): (princ "zzz")
zzz
"zzz"
USER(3): EOF
Really exit lisp [n]? 
; Exiting Lisp
$

-- 
Sam Steingold, running RedHat5 GNU/Linux (http://www.linux.org)
Micros**t is not the answer. Micros**t is a question, and the answer is Linux,
the choice of the GNU (http://www.gnu.org) generation.
"Complete Idiots Guide to Running LINUX Unleashed in a Nutshell for Dumbies"

---

From: Bruno Haible <[email-masked]>
Date: Thu, 26 Mar 1998 15:47:38 +0100 (MET)

[The following message is a courtesy copy of an article that has been
posted to comp.lang.lisp by Kent M Pitman <[email-masked]>.
I repost it here on my own responsibility. Sorry if you see it twice.  Bruno]

> wich changed this to zz. Who is right?

Remember that Lisp is somewhat schizo about the use of the names print
and prin1.   PRINT-OBJECT, for example, implements PRIN1, not PRINT.

PRIN1 is only so-called for ancient reasons.  It ought to have been named
PRINT and PRINT should have been named PRINT-ON-OWN-LINE or something.
But for reasons of history and compatibility, it wasn't.

*PRINT-READABLY* is best understood as *PRIN1-READABLY*.  Its role in life
is to bridge the gap between the fact that many things have a printed
representation that is re-readble, but many do not.  In particular,
hash tables, streams, etc. are not re-readable.  So there is nothing
more annoying than writing a program that does

 (DEFUN SAVE-ALL-MY-DATA-FOR-TOMORROW (FILE)
   (WITH-OPEN-FILE (STREAM FILE :DIRECTION :OUTPUT)
     (PRINT *ALL-MY-DATA* STREAM)))

only to find out  what was saved to a file was

  (FOO BAR ...)

or

  (FOO BAR #<STREAM ...>)

because tomorrow when I'm going to do

 (DEFUN READ-ALL-MY-DATA (FILE)
   (WITH-OPEN-FILE (STREAM FILE :DIRECTION :INPUT)
     (SETQ *ALL-MY-DATA* (READ STREAM)))))

I'm going to get a syntax error.  So *PRINT-READABLY* tells Lisp
that programs doing printing should err at PRINT-time when they
fully well know that the result will not be re-readable.  Much better
to know your save failed and that you need to take alternate action
(while the image is still running on day 1) than to find out later.

This has happened to me more than once in the olden days.  I'm sure
to others as well.  The fix was:

 (DEFUN SAVE-ALL-MY-DATA-FOR-TOMORROW (FILE)
   (WITH-OPEN-FILE (STREAM FILE :DIRECTION :OUTPUT)
     (LET ((*PRINT-READABLY* T))
       (PRINT *ALL-MY-DATA* STREAM))))

[Actually, there are aalso "typical bugs" related to mismatch of
package, etc, too.  Hence really,

 (DEFUN SAVE-ALL-MY-DATA-FOR-TOMORROW (FILE)
   (WITH-OPEN-FILE (STREAM FILE :DIRECTION :OUTPUT)
     (WITH-STANDARD-IO-SYNTAX
       (PRINT *ALL-MY-DATA* STREAM))))

is better; it binds not only *PRINT-READABLY* but a number of
other things people often forget to bind that they should.

Now comes the problem of PRINC.

Here's a fact worth noting:

      No one calls PRINC ever in files to be
      re-readable so it's just nutty to change it's behavior.
      That is, if a program does:
        (PRINC *ALL-MY-DATA* STREAM)
      or even (PRINC *SOME-OF-MY-DATA* STREAM)
      we know that one of these things is true:
        (a) you're lost whether or not you're using *print-readably*
        (b) you're not re-reading with READ
        (c) you're implementing PRINT using PRINC as a sub-primitive.

Here's another observation:

 print-object methods often call PRINC out of tradition, often where
 write-string is desired.    Some of this is tradition.  Some is
 becuase ~A in format is used and there is no write-string operation
 in format.  Having *print-readably* randomly turn a ~A into ~S would
 be an unmitigated disaster becuase it would break print-object
 methods everywhere, making them insert quotes, backslashes, etc.
 all over the place.

As Erik points out, as far as the spec goes, there is no question
(PRINC "FOO") should print FOO, not "FOO" no matter the binding of
*PRINT-ESCAPE* or *PRINT-READABLY* that prevails outside the call to
PRINC, since PRINC binds both of these variables to false while it
executes, and so no code within it would be aware of the values
prevailing outside.

But I thought you might want to see the history/motivation so you
could feel comfortable that this is not an accident or typo.