Next: , Previous: Format, Up: Input/Output


14.7 Custom Output

MIT/GNU Scheme provides hooks for specifying that certain kinds of objects have special written representations. There are no restrictions on the written representations, but only a few kinds of objects may have custom representation specified for them, specifically: records (see Records), vectors that have special tags in their zero-th elements (see Vectors), and pairs that have special tags in their car fields (see Lists). There is a different procedure for specifying the written representation of each of these types.

— procedure: set-record-type-unparser-method! record-type unparser-method

Changes the unparser method of the type represented by record-type to be unparser-method, and returns an unspecified value. Subsequently, when the unparser encounters a record of this type, it will invoke unparser-method to generate the written representation.

— procedure: unparser/set-tagged-vector-method! tag unparser-method

Changes the unparser method of the vector type represented by tag to be unparser-method, and returns an unspecified value. Subsequently, when the unparser encounters a vector with tag as its zero-th element, it will invoke unparser-method to generate the written representation.

— procedure: unparser/set-tagged-pair-method! tag unparser-method

Changes the unparser method of the pair type represented by tag to be unparser-method, and returns an unspecified value. Subsequently, when the unparser encounters a pair with tag in its car field, it will invoke unparser-method to generate the written representation.

An unparser method is a procedure that is invoked with two arguments: an unparser state and an object. An unparser method generates a written representation for the object, writing it to the output port specified by the unparser state. The value yielded by an unparser method is ignored. Note that an unparser state is not an output port, rather it is an object that contains an output port as one of its components. Application programs generally do not construct or examine unparser state objects, but just pass them along.

There are two ways to create an unparser method (which is then registered by one of the above procedures). The first, and easiest, is to use standard-unparser-method. The second is to define your own method using the procedure with-current-unparser-state. We encourage the use of the first method, as it results in a more uniform appearance for objects. Many predefined datatypes, for example procedures and environments, already have this appearance.

— procedure: standard-unparser-method name procedure

Returns a standard unparser method. Name may be any object, and is used as the name of the type with which the unparser method is associated; name is usually a symbol. Procedure must be #f or a procedure of two arguments.

If procedure is #f, the returned method generates an external representation of this form:

          #[name hash]

Here name is the external representation of the argument name, as generated by write,1 and hash is the external representation of an exact non-negative integer unique to the object being printed (specifically, it is the result of calling hash on the object). Subsequently, the expression

          #@hash

is notation for the object.

If procedure is supplied, the returned method generates a slightly different external representation:

          #[name hash output]

Here name and hash are as above, and output is the output generated by procedure. The representation is constructed in three stages:

  1. The first part of the format (up to output) is written to the output port specified by the unparser state. This is "#[", name, " ", and hash.
  2. Procedure is invoked on two arguments: the object and an output port.
  3. The closing bracket is written to the output port.

The following procedure is useful for writing more general kinds of unparser methods.

— procedure: with-current-unparser-state unparser-state procedure

This procedure calls procedure with one argument, the output port from unparser-state. Additionally, it arranges for the remaining components of unparser-state to be given to the printer when they are needed. The procedure generates some output by writing to the output port using the usual output operations, and the value yielded by procedure is returned from with-current-unparser-state.

The port passed to procedure should only be used within the dynamic extent of procedure.


Footnotes

[1] Except that if the argument name is a string, its external representation is generated by write-string.