Sometimes a particular data representation is imposed by external requirements,
and yet it is desirable to document the data format as a defstruct-style
structure. For example, consider expressions built up from numbers,
symbols, and binary operations such as + and *. An operation
might be represented as it is in Lisp, as a list of the operator
and the two operands. This fact can be expressed succinctly with defstruct
in this manner:

This will define a constructor function make-binop and three
selector functions, namely binop-operator, binop-operand-1,
and binop-operand-2. (It will not, however, define a predicate
binop-p, for reasons explained below.)

It is just like the function list except that it takes
keyword arguments and performs slot defaulting appropriate to the binop
conceptual data type. Similarly, the selector functions
binop-operator, binop-operand-1,
and binop-operand-2 are essentially equivalent to car,
cadr, and caddr, respectively. (They might not be
completely equivalent because,
for example, an implementation would be justified in adding error-checking
code to ensure that the argument to each selector function is a length-3
list.)

We speak of binop as being a ``conceptual'' data type because binop
is not made a part of the Common Lisp type system. The predicate
typep will not recognize binop as a type specifier, and type-of
will return list when given a binop structure. Indeed, there is
no way to distinguish a data structure constructed by make-binop
from any other list that happens to have the correct structure.

There is not even any way to recover the structure name binop from
a structure created by make-binop. This can be done, however,
if the structure is ``named.''