References: FORMAT (pp. 385-388), PRIN1 (p. 83), PRINC (p. 83),
WRITE (p. 382), *PRINT-PRETTY* (p. 371)
Related Issues: DATA-IO, FORMAT-PRETTY-PRINT, PRINT-CIRCLE-SHARED
Edit history: Version 1 by Moon 9/25/91
What do you think this form outputs?
(let ((*print-readably* t))
(format t "<~A>" '|Foo|))
If you said <Foo>, that's what I expect it to output. However a close
reading of CLtL2 shows that it is specified to print <|Foo|>. Similarly
~A is specified to put on a package prefix if ~S would, when
*PRINT-READABLY* is T. ~D, etc. have the same problem, as does PRINC.
If *PRINT-READABLY* is true, the binding of *PRINT-ESCAPE* by these
FORMAT operators and by PRINC has no effect.
See CLtL2 p.558 for the specification that *print-readably* overrides
*print-escape*, CLtL2 p.583 for the specification that ~A only binds
the printer control variables it is explicitly specified to bind,
CLtL2 p.584 for the specification that ~A only binds *print-escape*
(*print-readably* is not listed), and CLtL2 p.578 for the specification
that princ is the same as write with :escape nil (but not :readably nil).
Part of the problem appears to be that issue DATA-IO was written up
without any reference to issue FORMAT-PRETTY-PRINT. I apologize.
A related problem is that the following form
(let ((*print-circle* t) (s "foo"))
(format t "~A ~A(~A, ~A)"
"moe" "bar" s s))
is specified to print ``moe bar(#1=foo, #1#)'' rather than
printing ``moe bar(foo, foo)''.
I discovered these problems when Macintosh Common Lisp was changed to
obey the letter of the law (as handed down in CLtL2) and a program of
mine stopped working.
1. Specify that ~A binds *PRINT-READABLY* to NIL.
2. Specify the same for ~B, ~D, ~E, ~F, ~G, ~O, ~nR, ~X, and ~$ (which
all turn into ~A for non-numeric arguments).
3. Change the specification of (PRINC object stream) as equivalent to
(WRITE object :STREAM stream :ESCAPE NIL)
to instead be equivalent to
(WRITE object :STREAM stream :ESCAPE NIL :READABLY NIL)
4. Change PRINC-TO-STRING the same way.
5. Change items 1 and 2 above also to bind *PRINT-CIRCLE* to NIL.
Change items 3 and 4 above also to specify :CIRCLE NIL.
This has been broken out into a separate numbered item to allow
for the possibility of voting separately on this change.
See "Problem description."
Proposal DATA-IO:ADD-SUPPORT was not intended to "break" ~A;
this was an accident.
~A and PRINC are supposed to produce "human-readable" output, so
they should not put on machine-readability decorations such as
vertical bars, backslashes, package prefixes, and #1#.
Point 5 means that ~A might not terminate when given a circular
structure to print, even if *PRINT-CIRCLE* is true. The real problem
here is that *PRINT-CIRCLE* is being used for two distinct purposes,
detecting circular structure and detecting shared structure. We do
not propose here to separate those two features (X3J13 voted
down a proposal, PRINT-CIRCLE-SHARED:NEW-VARIABLE, to do so once before).
Macintosh Common Lisp 2.0b3c4 does not implement this proposal; it
implements exactly what CLtL2 specifies.
Symbolics Genera 8.1 implements the proposal, or at least produces the
proposed result for both test cases. This might be due to assuming
that CLtL2 says something reasonable rather than reading the book with
a magnifying glass.
Cost to Implementors:
Implementing the changes should take very little effort.
Cost to Users:
Conceivably existing code could depend on the specified behavior,
but that seems quite unlikely, so the cost to users is probably minimal.
Cost of non-Adoption:
A silly hassle for anyone using ~A and ~S to generate comments and
code respectively, with *PRINT-READABLY* and/or *PRINT-CIRCLE* turned
on for the benefit of the ~S.
Fewer silly hassles.
Does FORMAT have aesthetics? If it does, I think the change improves
Dave Moon and Guy Steele were both surprised that CLtL2 says what it says.