[LISPWORKS][Common Lisp HyperSpec (TM)] [Previous][Up][Next]


Issue GENERALIZE-PRETTY-PRINTER Writeup

Forum:		Public Review

Issue: GENERALIZE-PRETTY-PRINTER

References: Loosemore's public review comment #18 (X3J13/92-1318)

Section 22.2.1 (Pretty Printer Concepts), p 22-13

~/name/ FORMAT directive, p 22-39..22-40

PPRINT-DISPATCH, p 22-45..22-46

PPRINT-EXIT-IF-LIST-EXHAUSTED, p 22-46

PPRINT-FILL (etc), p 22-47

PPRINT-INDENT, p 22-48

PPRINT-LOGICAL-BLOCK, p 22-49..22-51

PPRINT-NEWLINE, p 22-51..22-52

PPRINT-POP, p 22-52..22-54

PPRINT-TAB, p 22-54

PRINT-OBJECT, p 22-55..22-56

SET-PPRINT-DISPATCH, p 22-57..22-58

Category: CHANGE

Edit history: V1, 18 Sept 1992, Sandra Loosemore

V2, 18 Sept 1992, Sandra Loosemore

(comments from Dick Waters)

V3, 04 Feb 1993, Sandra Loosemore

(fix references)

Status: Proposal UNIFY passed 8-3 on letter ballot 93-302.

Problem description:

The pretty-printing mechanisms are poorly integrated with the rest

of the printer.

Specifically,

(1) The requirement that objects for which there is no pretty-print

function defined in *PRINT-PPRINT-DISPATCH* print using the standard

mechanisms but with *PRINT-PRETTY* bound to NIL (p. 22-15 and 22-45)

makes it impossible for PRINT-OBJECT methods or DEFSTRUCT

:PRINT-FUNCTIONS to handle *PRINT-PRETTY* themselves. This can lead

to unnecessary duplication of code, as it requires programmers to write

two different functions to print the same kind of object.

(2) The behavior of PPRINT-FILL, PPRINT-LINEAR, PPRINT-TABULAR,

PPRINT-INDENT, PPRINT-LOGICAL-BLOCK, PPRINT-NEWLINE, and PPRINT-TAB when

*PRINT-PRETTY* is not true is unspecified, although the names imply

that they are only useful when pretty-printing or that they may bind

*PRINT-PRETTY*. Again, to avoid pointless duplication of code, these

mechanisms should do something reasonable regardless of whether

*PRINT-PRETTY* is true.

(3) The order of the "stream" and "object" arguments to

PPRINT-FILL, PPRINT-LINEAR, PPRINT-TABULAR, functions in pprint

dispatch tables, and functions used with the ~/name/ format directive

is backwards with respect to that of other printing functions.

There are three non-mutually-exclusive proposals here. Proposal

UNIFY addresses problems (1) and (2). Proposal REORDER addresses

problem (3). Proposal RENAME changes the names of most of the

affected functions to reflect the more general utility under proposal

UNIFY.

Proposal (GENERALIZE-PRETTY-PRINTER:UNIFY):

(1) Change the behavior stated in section 22.2.1.4 and in the

description of PPRINT-DISPATCH to say that if there is no specific

found in the pprint dispatch table, a function which invokes the

appropriate PRINT-OBJECT method is used. Remove the requirement that

*PRINT-PRETTY* be rebound to NIL.

(2) Clarify that PPRINT-LOGICAL-BLOCK may be used even when

*PRINT-PRETTY* is not true. Remove the requirement that the stream

cease to behave as a pretty-printing stream if *PRINT-PRETTY* becomes

bound to NIL. Clarify that PPRINT-LOGICAL-BLOCK does not locally

rebind *PRINT-PRETTY*.

(3) Specify that if *PRINT-PRETTY* is false, the functions PPRINT-FILL,

PPRINT-LINEAR, and PPRINT-TABULAR print list arguments with a minimum

of whitespace (i.e., as described in section 22.1.3.8). Clarify that

these functions do not locally rebind *PRINT-PRETTY*.

(4) The draft currently says that PPRINT-NEWLINE, PPRINT-TAB, and

PPRINT-INDENT do nothing if the stream is not a pretty-printing stream.

Change this to say they also do nothing if *PRINT-PRETTY* is false.

(5) Change the description of PRINT-OBJECT to mention the use of

functions such as PPRINT-FILL to handle *PRINT-PRETTY*, and

PPRINT-LOGICAL-BLOCK to handle *PRINT-LENGTH* truncation, instead

of discouraging people from handling these variables properly.

Rationale:

This allows you to write a single function that handles both pretty

and non-pretty printing that can use a single block of code inside

PPRINT-LOGICAL-BLOCK to print structured objects regardless of whether

*PRINT-PRETTY* is true. It also allows you to call the other

functions without having to make an explicit check to be sure that

*PRINT-PRETTY* is true, and do something else if it isn't.

Proposal (GENERALIZE-PRETTY-PRINTER:REORDER):

(1) Reverse the order of the "object" and "stream" arguments to

functions in pprint dispatch tables.

(2) Explicitly state that PPRINT-DISPATCH returns the generic function

PRINT-OBJECT if there is no matching type specifier in the pprint

dispatch table.

(3) Reverse the order of the "object" and "stream" arguments to

PPRINT-FILL, PPRINT-LINEAR, and PPRINT-TABULAR. Make the "stream"

argument optional and default in the usual way for an output stream

designator, so that the argument list is

(object &optional stream colon-p at-sign-p).

(4) Reverse the order of the "object" and "stream" arguments passed

to functions invoked with the ~/name/ format directive.

Rationale:

This removes a pointless inconsistency in the language design and

makes it a little simpler.

Proposal (GENERALIZE-PRETTY-PRINTER:RENAME):

Rename PPRINT-EXIT-IF-LIST-EXHAUSTED, PPRINT-FILL, PPRINT-LINEAR,

PPRINT-TABULAR, PPRINT-INDENT, PPRINT-LOGICAL-BLOCK, PPRINT-NEWLINE,

PPRINT-POP, and PPRINT-TAB to PRINT-*.

Rationale:

Changing the names makes it more apparent that these functions are

useful even when *PRINT-PRETTY* is false and that they do not

rebind *PRINT-PRETTY* to true as PPRINT does. (Note that this list

does not include *PRINT-PPRINT-DISPATCH*, PPRINT-DISPATCH, and

SET-PPRINT-DISPATCH, since these are only relevant when *PRINT-PRETTY*

is true.)

Since proposals UNIFY and REORDER make incompatible changes in the

behavior of these functions, changing their names may be helpful in

detecting obsolete calls.

Current practice:

XP doesn't implement any of these changes.

Loosemore made most of these changes when rewriting XP into a

Scheme-like dialect; the Yale Haskell system uses it extensively.

Cost to implementors:

Medium. Making the changes to the printer implementation is

straightforward, but there are the usual support costs associated

with making an incompatible change.

Cost to users:

This is an incompatible change for people who now use XP, but it's

easy to fix. Adoption of proposal RENAME may make it easier to detect

obsolete uses.

Cost of non-adoption:

More work for people writing new code. Confusion about why

PRINT-OBJECT methods can't detect when *PRINT-PRETTY* is true. Risk

of function for printing when *PRINT-PRETTY* is true getting out of

sync with function for printing the same object when *PRINT-PRETTY* is

false. Risk of people making stupid programming mistakes because they

can't remember which functions accept arguments in which order.

Benefits:

The cost of non-adoption is avoided.

Aesthetics:

Making the language simpler and more uniform is generally a good

thing.

Editorial impact:

It would probably take two or three days to make the necessary changes,

including updating examples. Loosemore is willing to undertake the

editorial work.

Discussion:

This issue was first raised on the X3J13 mailing list in January 1992

with the subject "apparent shortcomings with PPRINT interface".

Loosemore says: I discovered these problems when trying to implement

the new pretty-printer functionality for the first time for use by the

Yale Haskell system. We have several dozen different kinds of structures

representing AST nodes and wanted to be able to print them reasonably

for debugging and error messages. Pushing the detection for

*PRINT-PRETTY* into the support functions resulted in *major*

consolidations and simplifications of this code.

Waters says: I support your proposal strongly. Please feel free to

add me to the proposal as a formal supporter.

John Burger also says he was bitten by the inability to handle

*PRINT-PRETTY* in PRINT-OBJECT methods, and that he supports this

proposal.


[Starting Points][Contents][Index][Symbols][Glossary][Issues]
Copyright 1996-2005, LispWorks Ltd. All rights reserved.