When *print-pretty* is not nil, the pprint dispatch table in the variable *print-pprint-dispatch* controls how objects are printed. The information in this table takes precedence over all other mechanisms for specifying how to print objects. In particular, it overrides user-deﬁned print-object methods and print functions for structures. However, if there is no speciﬁcation for how to pretty print a particular kind of object, it is then printed using the standard mechanisms as if *print-pretty* were nil.
A pprint dispatch table is a mapping from keys to pairs of values. The keys are type speciﬁers. The values are functions and numerical priorities. Basic insertion and retrieval is done based on the keys with the equality of keys being tested by equal. The function to use when pretty printing an object is chosen by ﬁnding the highest priority function in *print-pprint-dispatch* that is associated with a type speciﬁer that matches the object.
[Function]copy-pprint-dispatch &optional table
[Function]pprint-dispatch object &optional table
This retrieves the highest priority function from a pprint table that is associated with a type speciﬁer in the table that matches object. The function is chosen by ﬁnding all the type speciﬁers in table that match the object and selecting the highest priority function associated with any of these type speciﬁers. If there is more than one highest priority function, an arbitrary choice is made. If no type speciﬁers match the object, a function is returned that prints object with *print-pretty* bound to nil.
As a second return value, pprint-dispatch returns a ﬂag that is t if a
matching type speciﬁer was found in table and nil if not.
Table(which defaults to *print-pprint-dispatch*) must be a pprint dispatch table. Table can be nil, in which case retrieval is done in the initial value of *print-pprint-dispatch*.
[Function]set-pprint-dispatch type function &optional priority table
This puts an entry into a pprint dispatch table and returns nil. The type must be a valid type speciﬁer and is the key of the entry. The ﬁrst action of set-pprint-dispatch is to remove any pre-existing entry associated with type. This guarantees that there will never be two entries associated with the same type speciﬁer in a given pprint dispatch table. Equality of type speciﬁers is tested by equal.
Two values are associated with each type speciﬁer in a pprint dispatch table: a function and a priority. The function must accept two arguments: the stream to send output to and the object to be printed. The function should pretty print the object on the stream. The function can assume that object satisﬁes type. The function should obey *print-readably*. Any values returned by the function are ignored.
The priority (which defaults to 0) must be a non-complex number. This number is used as a priority to resolve conﬂicts when an object matches more than one entry. An error is signaled if priority fails to be a non-complex number.
The table (which defaults to the value of *print-pprint-dispatch*) must be a pprint dispatch table. The speciﬁed entry is placed in this table.
To facilitate the use of pprint dispatch tables for controlling the pretty printing of Lisp code, the type-speciﬁer argument of the function set-pprint-dispatch is allowed to contain the form (cons car-type cdr-type). This form indicates that the corresponding object must be a cons whose car satisﬁes the type speciﬁer car-type and whose cdr satisﬁes the type speciﬁer cdr-type. The cdr-type can be omitted, in which case it defaults to t.
The initial value of *print-pprint-dispatch* is implementation-dependent. However, the initial entries all use a special class of priorities that are less than every priority that can be speciﬁed using set-pprint-dispatch. This guarantees that pretty printing functions speciﬁed by users will override everything in the initial value of *print-pprint-dispatch*.
Consider the following examples. The ﬁrst form restores *print-pprint-dispatch* to its initial value. The next two forms then specify a special way of pretty printing ratios. Note that the more speciﬁc type speciﬁer has to be associated with a higher priority.
The following two forms illustrate the speciﬁcation of pretty printing functions for particular types of Lisp code. The ﬁrst form illustrates how to specify the traditional method for printing quoted objects using “’” syntax. Note the care taken to ensure that data lists that happen to begin with quote will be printed readably. The second form speciﬁes that lists beginning with the symbol my-let should print the same way that lists beginning with let print when the initial pprint dispatch table is in eﬀect.
The next example speciﬁes a default method for printing lists that do not correspond to function calls. Note that, as shown in the deﬁnition of pprint-tabular above, pprint-linear, pprint-ﬁll, and pprint-tabular are deﬁned with optional colon and atsign arguments so that they can be used as pprint dispatch functions as well as ~/.../ functions.
With a line length of 9, (pprint ’(0 b c d e f g h i j k)) prints:
This ﬁnal example shows how to deﬁne a pretty printing function for a user deﬁned data structure.
The pretty printing function for the structure family speciﬁes how to adjust the layout of the output so that it can ﬁt aesthetically into a variety of line widths. In addition, it obeys the printer control variables *print-level*, *print-length*, *print-lines*, *print-circle*, *print-shared*, and *print-escape*, and can tolerate several diﬀerent kinds of malformity in the data structure. The output below shows what is printed out with a right margin of 25, *print-pretty* t, *print-escape* nil, and a malformed kids list.
Note that a pretty printing function for a structure is diﬀerent from the structure’s print function. While print functions are permanently associated with a structure, pretty printing functions are stored in pprint dispatch tables and can be rapidly changed to reﬂect diﬀerent printing needs. If there is no pretty printing function for a structure in the current print dispatch table, the print function (if any) is used instead.