Abstract: The "mode" package described here enables users to define compound data types to the MACLISP interpreter and compiler. A mode is defined by specifying a data structure with named components; the user may then construct instances of the mode and select from or assign to components of any instance. This "data macro" capability facilitates changes in representation, adds meaning to selection and assignment operations by naming components, and provides rudimentary type checking. Its use entails absolutely no overhead in compiled code. A mode is a description of a class of data objects which share a specified structural description. Each of MACLISP's primitive data types is a mode; and a programmer may define his own composite modes by specifying its desired structure. By defining a mode, the programmer implicitly creates construction, selection, and assignment operators for manipulating instances of the mode (hereafter called "tokens") and allows the compiler to open code these operations and optimize where possible. As an example of how modes are used, consider the following data type used in a program for manipulating "fuses". A new mode is defined with the command DEFMODE; here each fuse is represented by a list, the first entry of which is the symbol FUSE, followed by the manufacturer, its rating, and the price. The symbols in angle brackets are the names of the components of the mode. => (DEFMODE FUSE () (LIST 'FUSE )) FUSE The construction function resulting from a mode definition can be used to create an instance of the mode. The token is generated using the structural description specified in the definition, with the named slots filled by the arguments to the construction function. => (SETQ F1 (C-FUSE 'GE 20 13)) (FUSE GE 20 13) The selection and assignment operators can be used to access or modify components of such tokens. => :F1:RATING 20 => :F1:PRICE 13 => (<- :F1:MAN 'WESTINGHOUSE) WESTINGHOUSE => F1 (FUSE WESTINGHOUSE 20 13) In order for MACLISP to do type checking, the programmer must specify the mode of each component he wants checked. As will be discussed in the section on selection, this information is also necessary in choosing the appropriate selection function whenever compound modes are used. The mode restriction of a component is specified by a second entry in angle brackets after the component name. => (DEFMODE FUSEBOX () (CONS )) FUSEBOX Here each component of a FUSEBOX is constrained to be a FUSE. => (SETQ F2 (C-FUSE 'GE 40 19)) (FUSE GE 40 19) => (SETQ FB (C-FUSEBOX F1 F2)) ((FUSE WESTINGHOUSE 20 13) FUSE GE 40 19) => :FB:B (FUSE GE 40 19) => :FB:B:PRICE 19 => (_ :FB:B:PRICE 29) 29 => FB ((FUSE WESTINGHOUSE 20 13) FUSE GE 40 29) Other syntactic sugar is described in detail below. The design policy behind the mode package is to minimize programmer effort by choosing reasonable defaults for frequently performed data manipulations. Thus, a programmer may leave the choice of representation to the system by use of the STRUCT descriptor, the meaning of which is a class of data objects with specified components but unspecified structure. => (DEFMODE FUSE () (STRUCT )) FUSE => (C-FUSE 'GE 20 13) (GE 20 . 13) Here MACLISP chose a list structure representation for fuses using two CONS cells. Selection and assignment operators are defined accordingly. Sections 2, 3, and 4 of this primer describe the full usage and implementation details of mode definition, selection, and assignment. The casual user may omit these sections until he has need for them and may skip to section 5, which describes how to use the mode package, and to the catalog of commands in section 6. Some theoretical reflections are presented in section 7. Section 5 - How to Use Modes with the Interpreter and Compiler Easy. Interpreter - do (FASLOAD MODE FASL DSK LIBLSP) Compiler - at head of file (DECLARE (FASLOAD MODE FASL DSK LIBLSP)) Everything else is automatic. Section 6 - Catalog of Commands (DEFMODE name () description) - defines a new mode called name, each token of which has the structural properties specified in description. The description of a mode is one of: (ATOM selector1 selector2 ... ) (STRUCT selector1 selector2 ... ) (CONS description1 description2) (LIST description1 description2 ... ) where a selector is a list of one, two, or three symbols in angle brackets. A shorthand notation for LIST and CONS using ! is also available. For example the following pairs are equivalent. (LIST 1 2 3) !(1 2 3) (CONS 'A (CONS 'B 'C)) !(A B . C) (MODEDECLARE (mode1 code1 code2 ... ) (mode2 code3 code4 ... ) ... ) - declares code1, code2, ... to return values of mode mode1, etc. The declaration is in force until cancelled by a later declaration. :BASE1:SELECTOR1:SELECTOR2:... - selects the component form base1 named selector1, then repeats process with result and selector2 until no more selectors. (_ :BASE1:SELECTOR1:SELECTOR2:... VAL1 :BASE2:SELECTOR3:... VAL2 ... ) - assigns VAL1 to component specified by the first argument, does the same for VAL2 and the third argument, etc.