Re: Problem with SBCL pprint
Richard M Kreuter via Sbcl-help <[email protected]> Wed, 08 Apr 2026 17:24:08 -0400
| Newsgroups | gmane.lisp.steel-bank.general |
|---|---|
| Message-ID | <[email protected]> |
Douglas Katzman <[email protected]> wrote: > [ANSI] says that ~D,~B,~O,~X,~R (and others) rebind printer > controls... [W]hat's the point of specifying mandatory rebindings if > not to either permit or require user-written functions to take over > the printing as per the print-pretty mechanism? ~D,~B,~O,~X,~nR print a non-integer argument "as by PRINC". So the mandatory rebindings have an effect when the argument isn't an integer. What if that was the only point? In fact, the rules about variable rebinding were finalized months before Waters's pretty printer was proposed (note the draft dates): https://www.lispworks.com/documentation/HyperSpec/Issues/iss169_w.htm https://www.lispworks.com/documentation/HyperSpec/Issues/iss270_w.htm And before Waters's pretty printer, the variable binding rules could not have had an observable effect on output from conforming programs' uses of ~D,~O,~B,~X,~R when the argument is an integer. So the original point of variable binding rules could not have had to do with pretty printing. I don't think Waters's pretty printer compelled a reinterpretation of the role of those rules, as I'll explain below. (Candidly, I can't offer a rationale for every binding FORMAT-PRETTY-PRINT required. Some seem unnecessary or redundant, and the Cleanup committee thread looks like bikeshedding.) Douglas Katzman <[email protected]> wrote: > Based on some discussion here, I think we would be receptive to > well-reasoned claims that ~D,~O,~B,~X "definitely" meant that a value > is output exactly as specified in the writeup for that directive > regardless of *print-pretty*, provided the value is an integer. I > think the claim would be along the line that use of PRINC was merely a > hidden detail of the implementation in some cases, not a mandate to > use it, and that CLHS allows either interpretation of whether to > respect *print-pretty* except in the case when PRINC _must_ be called > due to the fallback to "~A" when the argument is not an > integer. Something like that. I'll stipulate I can't find anything in CLHS to disambiguate things. However, I don't think the implemented behavior was intended or the Right Thing for any directives that aren't required to invoke the printer (~W, ~S, ~A, and ones that fall through to ~A). I think intent is discoverable enough: Waters's XP, which was presented as a reference implementation of the pretty printer interface, only invoked a pretty printer function for ~W, ~S, ~A. This code is neither bug-free nor normative, but there's a long comment suggesting that his handling of ~C,~D,~O,~B,~X,~R,~F,~E,~G,~$ was deliberate. So ISTM likely that the reason his spec was silent about those directives is because he intended their behavior to remain constant. https://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/lang/lisp/code/io/xp/ What's more important is how/why that behavior could make sense. The canonical use of the pretty printing interface is to construct variants of the "vanilla" Lisp printer that produce extra whitespace & perhaps style certain things interestingly. The Lisp printer is parameterized by printer controls, and the entirety of a printed representation customarily presents all objects as if under a constant complement of printer control settings. FORMAT directives that present an atom force styling that disagrees with the Lisp printer: each of ~C,~D,~O,~B,~X,~R,~A,~S, overrule some printer control variable, and each of ~F,~E,~G,~$ is able to disagree with PRIN1 for some float. So canonical pretty printer applications won't use these directives very much. (I believe SBCL's pretty printer has just one use: ~D for an array's rank. More on that below.) If canonical uses won't involve ~C,~D,~O,~B,~X,~R,~F,~E,~G,~$, why have them invoke pretty printer functions? And if there are other, non-canonical applications (like Robert's) that could use ~C,~D,~O,~B,~X,~R,~F,~E,~G,~$ for their standard styling effects, isn't it more convenient for the user not to have to worry about regress? That is, making ~C,~D,~O,~B,~X,~R,~F,~E,~G,~$ "base cases" seems to be a pure win over the status quo. Moreover, making ~C,~D,~O,~B,~X,~R,~F,~E,~G,~$ base cases would eliminate some head-scratchers for users of SBCL. One head-scratcher is how to decide who's at fault here and what to do about it: * (let ((*print-pretty* t) (*print-pprint-dispatch* (copy-pprint-dispatch nil))) (set-pprint-dispatch 'integer (lambda (s i) i (write-string "AAA" s))) (time (sleep 1))) Evaluation took: AAA.00AAA seconds of real time 0.000AAA seconds of total run time (0.0000AAA user, 0.000AAA system) 0.10% CPU AAA forms interpreted AAA processor cycles AAA bytes consed A subtler head-scratcher is whether the fact that installing a custom integer printer does /not/ break how the rank appears in the output of (pprint (make-array '(2 2))) dependends on the head-scratcher that "~D" only /sometimes/ invokes a pretty printer function. Finally, and more abstractly, isn't it a more parsimonious interpretation of the standard to say that a FORMAT directive is to behave as if it invokes the Lisp printer only when the CLHS actually says it is to do so? Regards, Richard