;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*- =Node: Data Types =Text: 3DATA TYPES* This section enumerates some of the various different primitive types of objects in Zetalisp. The types explained below include symbols, conses, various types of numbers, two kinds of compiled code objects, locatives, arrays, stack groups, and closures. A 1symbol* (these are sometimes called ``atoms'' or ``atomic symbols'' by other texts) has a 1print name*, a 1value*, a 1definition*, a 1property list*, and a 1package*. The print name is a string, which may be obtained by the function 2symbol-name 4(SYMBOLS-1)The Print Name**). This string serves as the 1printed representation* (see 4(READPRINT-1)What the Printer Produces*) of the symbol. Each symbol has a 1value*, which may be any Lisp object. This is the value of the symbol when regarded as a dynamic variable. It is also referred to sometimes as the ``contents of the value cell'', since internally every symbol has a cell called the 1value cell*, which holds the value. It is accessed by the 2symeval* function (4(SYMBOLS-1)The Value Cell*), and updated by the 2set* function (4(SYMBOLS-1)The Value Cell*). (That is, given a symbol, you use 2symeval* to find out what its value is, and use 2set* to change its value.) Each symbol has a 1definition*, which may also be any Lisp object. It is also referred to as the ``contents of the function cell'', since internally every symbol has a cell called the 1function cell*, which holds the definition. The definition can be accessed by the 2fsymeval* function (4(SYMBOLS-1)The Function Cell*), and updated with 2fset* (4(SYMBOLS-1)The Function Cell*), although usually the functions 2fdefinition* and 2fdefine* are employed (4(FUNCTIONS-2)How Programs Manipulate Function Specs*). The property list is a list of an even number of elements; it can be accessed directly by 2plist* (4(SYMBOLS-1)The Property List*), and updated directly by 2setplist* (4(SYMBOLS-1)The Property List*), although usually the functions 2get*, 2putprop*, and 2remprop* (4(MANLISTSTR-2)Property Lists*) are used. The property list is used to associate any number of additional attributes with a symbol--attributes not used frequently enough to deserve their own cells as the value and definition do. Symbols also have a package cell, which indicates which package of names the symbol belongs to. This is explained further in the section on packages (chapter 4(PACKAGES-0)Packages*) and can be disregarded by the casual user. The primitive function for creating symbols is 2make-symbol* (4(SYMBOLS-1)Creating Symbols*), although most symbols are created by 2read*, 2intern*, or 2fasload* (which call 2make-symbol* themselves.) A 1cons* is an object that cares about two other objects, arbitrarily named the 1car* and the 1cdr*. These objects can be accessed with 2car* and 2cdr* (4(MANLISTSTR-1)Conses*), and updated with 2rplaca* and 2rplacd* (4(MANLISTSTR-1)Conses*). The primitive function for creating conses is 2cons* (4(MANLISTSTR-1)Conses*). There are several kinds of numbers in Zetalisp. 1Fixnums* represent integers in the range of -2^24 to 2^24-1. 1Bignums* represent integers of arbitrary size, but they are more expensive to use than fixnums because they occupy storage and are slower. The system automatically converts between fixnums and bignums as required. 1Floats* are floating-point numbers. 1Short floats* are another kind of floating-point numbers, with less range and precision, but less computational overhead. 1Ratios* are exact rational numbers that are represented with a numerator and a denominator, which are integers. 1Complexnums* are numbers that have explicitly represented real and imaginary parts, which can be any real numbers of the same type. See 4(NUMBERS-0)Numbers* for full details of these types and the conversions between them. A 1character object* is much like a fixnum except that its type is distinguishable. Common Lisp programs use character objects to represent characters. Traditional programs usually use fixnums to represent characters, although they can create an manipulate character objects when they desire. Character objects behave like fixnums when used in arithmetic; only a few operations make any distinction. They do, however, print distinctively. See 4(CHARSTR-1)Characters* for more information. The usual form of compiled, executable code is a Lisp object, called a ``Function Entry Frame'' or ``FEF'' for historical reasons. A FEF contains the code for one function. This is analogous to what Maclisp calls a ``subr pointer''. FEFs are produced by the Lisp Compiler (4(COMPILER-0)The Compiler*), and are usually found as the definitions of symbols. The printed representation of a FEF includes its name so that it can be identified. Another kind of Lisp object that represents executable code is a ``microcode entry.'' These are the microcoded primitive functions of the Lisp system, and any user functions compiled into microcode. About the only useful thing to do with any of these compiled code objects is to 1apply* it to arguments. However, some functions are provided for examining such objects, for user convenience. See 2arglist* (4(FUNCTIONS-2)How Programs Examine Functions*), 2args-info* (4(FUNCTIONS-2)How Programs Examine Functions*), 2describe* (4(MISCELL-1)Poking Around in the Lisp World*), and 2disassemble* (4(MISCELL-1)Poking Around in the Lisp World*). A 1locative* (see 4(LOCATIVES-0)Locatives*) is a kind of a pointer to a single memory cell anywhere in the system. The contents of this cell can be accessed by 2cdr* (see 4(MANLISTSTR-1)Conses*) and updated by 2rplacd* (see 4(MANLISTSTR-1)Conses*). An 1array* (see 4(ARRAYS-0)Arrays*) is a set of cells indexed by a tuple of integer subscripts. The contents of the cells may be accessed and changed individually. There are several types of arrays. Some have cells that may contain any object, while others (numeric arrays) may only contain small positive numbers. Strings are a type of array; the elements are character objects. A 1list* is not a primitive data type, but rather a data structure made up out of conses and the symbol 2nil*. See 4(MANLISTSTR-0)Manipulating List Structure*. =Node: Data Type Predicates =Text: 3DATA TYPE PREDICATES* A 1predicate* is a function that tests for some condition involving its arguments and returns the symbol 2t* if the condition is true, or the symbol 2nil* if it is not true. The following predicates are for testing what data type an object has. By convention, the names of predicates usually end in the letter `p' (which stands for `predicate'). The following predicates are for testing data types. These predicates return 2t* if the argument is of the type indicated by the name of the function, 2nil* if it is of some other type. 3symbolp* 1object* 2t* if 1object* is a symbol, otherwise 2nil*. 3nsymbolp* 1object* 2nil* if 1object* is a symbol, otherwise 2t*. 3listp* 1object* 2t* if 1object* is a cons, otherwise 2nil*. Note that this means 2(listp nil)* is 2nil* even though 2nil* is the empty list. [This may be changed in the future to work like 2cli:listp*. Since the current definition of 2listp* is identical to that of 2consp*, all uses of 2listp* should be changed to 2consp* unless the treatment of 2nil* is not of concern.] 3cli:listp* 1object* The Common Lisp version of 2listp* returns 2t* if 1object* is 2nil* or a cons. 3nlistp* 1object* 2t* if 1object* is anything besides a cons, otherwise 2nil*. 2(nlistp nil)* returns 2t*. [This may be changed in the future, if and when 2listp* is changed. Since the current definition of 2nlistp* is identical to that of 2atom*, all uses of 2nlistp* should be changed to 2atom* unless the treatment of 2nil* is not of concern.] 3atom* 1object* 2t* if 1object* is not a cons, otherwise 2nil*. This is the same as 2(not (consp 1object*))*. 3consp* 1object* 2t* if 1object* is a cons, otherwise 2nil*. At the moment, this is the same as 2listp*; but while 2listp* may be changed, 2consp* will 1never* be true of 2nil*. 3numberp* 1object* 2t* if 1object* is any kind of number, otherwise 2nil*. 3integerp* 1object* 3fixp* 1object* Return 2t* if 1object* is a representation of an integer, i.e. a fixnum or a bignum, otherwise 2nil*. 3floatp* 1object* 2t* if 1object* is a floating-point number, i.e. a full-size or short float, otherwise 2nil*. 3fixnump* 1object* 2t* if 1object* is a fixnum, otherwise 2nil*. 3bigp* 1object* 2t* if 1object* is a bignum, otherwise 2nil*. 3flonump* 1object* 2t* if 1object* is a full-size float, otherwise 2nil*. 3small-floatp* 1object* 2t* if 1object* is a short float, otherwise 2nil*. 3rationalp* 1object* 2t* if 1object* is an exact representation of a rational number; that is, if it is a fixnum, a bignum or a ratio. Otherwise 2nil*. 3complexp* 1object* 2t* if 1object* is a complexnum, a number explicitly represented as complex. Otherwise 2nil*. 3realp* 1object* 2t* if 1object* is a number whose value is real, otherwise 2nil*. Any fixnum, bignum, float (of either format) or ratio satisfies this predicate. So does a complexnum whose imaginary part is zero. 3characterp* 1object* 2t* if 1object* is a character object, otherwise 2nil*. 3stringp* 1object* 2t* if 1object* is a string, otherwise 2nil*. 3arrayp* 1object* 2t* if 1object* is an array, otherwise 2nil*. Note that strings are arrays. 3vectorp* 1object* 2t* if 1object* is an array of rank 1. 3bit-vector-p* 1object* 2t* if 1object* is an array of rank 1 that allows only 0 and 1 as elements. 3simple-vector-p* 1object* 2t* if 1object* is an array of rank 1, with no fill pointer and not displaced, that can have any Lisp object as an element. 3simple-bit-vector-p* 1object* 2t* if 1object* is an array of rank 1, with no fill pointer and not displaced, that allows only 0 and 1 as elements. 3simple-string-p* 1object* 2t* if 1object* is a string with no fill pointer and not displaced. 3functionp* 1object* &optional 1allow-special-forms* 2t* if 1object* is a function (essentially, something that is acceptable as the first argument to 2apply*), otherwise 2nil*. In addition to interpreted, compiled, and microcoded functions, 2functionp* is true of closures, select-methods (see 4(FUNCTIONS-1)Other Kinds of Functions*), and symbols whose function definition is 2functionp*. 2functionp* is not true of objects that can be called as functions but are not normally thought of as functions: arrays, stack groups, entities, and instances. As a special case, 2functionp* of a symbol whose function definition is an array returns 2t*, because in this case the array is being used as a function rather than as an object. If 1allow-special-forms* is specified and non-2nil*, then 2functionp* will be true of macros and special-form functions (those with quoted arguments). Normally 2functionp* returns 2nil* for these since they do not behave like functions. 3compiled-function-p* 1object* 3subrp* 1object* 2t* if 1object* is any compiled code object, otherwise 2nil*. The name 2subrp* is for Maclisp compatibility. 3special-form-p* 1symbol* 2t* if 1symbol* is defined as a function that takes some unevaluated args. Macros do not count as special forms. 2macro-function* can be used to test whether a symbol is defined as a macro, but you must be careful because it also returns a non-2nil* value for certain special forms. See the definition 2macro-function* (4(MACROS-3)Definitions of Macros*) to find out how to do this properly. 3closurep* 1object* 2t* if 1object* is a closure, otherwise 2nil*. 3entityp* 1object* 2t* if 1object* is an entity, otherwise 2nil*. See 4(CLOSURES-1)Entities* for information about entities. 3locativep* 1object* 2t* if 1object* is a locative, otherwise 2nil*. 3commonp* 1object* 2t* if 1object* is of a type that Common Lisp defines operations on. See the type specifier 2common* (4(PRIMOBJTYPE-1)Common LISP Compatibility Types*). Other standard type predicates include 2packagep* (see 4(PACKAGES-1)Packages as Lisp Objects*), 2random-state-p* (see 4(NUMBERS-2)Random Numbers*), 2hash-table-p* (4(MANLISTSTR-3)Hash Table Functions*), 2pathnamep* (4(FILENAMES-1)Pathnames*), 2streamp* (4(IOSYSTEM-2)I/O Streams*) and 2readtablep* (4(READPRINT-4)The Readtable*). 2defstruct* can define additional type predicates automatically (4(DEFSTRUCT-1)Options to Defstruct*). =Node: Introduction to Type Specifiers =Text: 3INTRODUCTION TO TYPE SPECIFIERS* Data types can be represented symbolically by Lisp objects called 1type specifiers*. A type specifier describes a class of possible Lisp objects; the function 2typep* tells whether a given object matches a given type specifier. Built-in type specifiers exist for the actual Lisp Machine data types. The user can define additional type specifiers to represent arbitrary classifications of data. Type specifiers can also be combined into specifiers for more complex types. Some type specifiers are symbols: for example, 2number*, 2cons*, 2symbol*, 2integer*, 2character*, 2compiled-function*, 2array*, 2vector*. Their meanings are mostly obvious, but a table follows below. Type specifiers that are symbols are called 1simple* type specifiers. Lists can also be type specifiers. They are usually combinations or restrictions of other type specifiers. The car of the list is the key to understanding what it means. An example of a combination is 2(or array symbol)*, which matches any array or any symbol. An example of a restriction type is 2(integer 0 6)*, which matches only integers between 0 and 6 (inclusive). =Node: Basic Data Types =Text: 3BASIC DATA TYPES 2cons** non-2nil* lists. 2symbol* symbols. 2array* all arrays, including strings. 2number* numbers of all kinds. 2instance* all instances of any flavor. 2structure* named structures of any structure type. 2locative* locatives. 2closure* closures. 2entity* entities. 2stack-group* stack groups. 2compiled-function* macrocode functions such as the compiler makes. 2microcode-function* built-in functions implemented by the microcode. 2select* select-method functions (defined by 2defselect* or 2defselect-incremental*). 2character* character objects. =Node: Other Useful Simple Types =Text: 3OTHER USEFUL SIMPLE TYPES 2t** all Lisp objects belongs to this type. 2nil* nothing belongs to this type. 2string-char* characters that can go in strings. 2standard-char* characters defined by Common Lisp. These are the 95 ASCII printing characters (including 2Space*), together with 2Return*. 2null* 2nil* is the only object that belongs to type 2null*. 2list* lists, including 2nil*. This type is the union of the types 2null* and 2cons*. 2sequence* lists and vectors. Many Common Lisp functions accept either a list or a vector as a way of describing a sequence of elements. 2keyword* keywords (symbols belonging to package 2keyword*). 2atom* anything but conses. =Node: Simple Number Types =Text: 3SIMPLE NUMBER TYPES 2integer** fixnums and bignums. 2ratio* explicit rational numbers, such as 21\2* (21/2* in Common Lisp syntax). 2rational* integers and ratios. 2fixnum* small integers, whose 2%data-type* is 2dtp-fix* and which occupy no storage. 2bignum* larger integers, which occupy storage. 2bit* very small integers--only 20* and 21* belong to this type. 2float* any floating point number regardless of format. 2short-float* short floats 2single-float* full-size floats 2double-float* 2long-float*defined by Common Lisp, but on the Lisp Machine synonymous with 2single-float*. 2real* any number whose value is real. 2complex* a number explicitly stored as complex. It is possible for such a number to have zero as an imaginary part but only if it is a floating point zero. 2noncomplex* a number which is not explicitly stored as complex. This is a subtype of 2real*. =Node: Restriction Types for Numbers =Text: 3RESTRICTION TYPES FOR NUMBERS 2(complex 1type-spec*)** complex numbers whose components match 1type-spec*. Thus, 2(complex rational)* is the type of complex numbers with rational components. 2(complex t)* is equivalent to 2complex*. 2(integer 1low* 1high*)* integers between 1low* and 1high*. 1low* can be: 1integer* 1integer* is an inclusive lower limit 2(1integer*)* 1integer* is an exclusive lower limit. 2** There is no lower limit. 1high* has the same sorts of possibilities. If 1high* is omitted, it defaults to 2**. If both 1low* and 1high* are omitted, you have 2(integer)*, which is equivalent to plain 2integer*. Examples: 3(integer 0 *) *matches any nonnegative integer. 3(integer 0) *matches any nonnegative integer. 3(integer -4 3) *matches any integer between -4 and 3, inclusive. 3(integer -4 (4)) *matches any integer between -4 and 3, inclusive. 2bit* is equivalent to 2(integer 0 1)*. 2(rational 1low* 1high*)* 2(float 1low* 1high*) (short-float 1low* 1high*) (single-float 1low* 1high*) (double-float 1low* 1high*) (long-float 1low* 1high*) (noncomplex 1low* 1high*)*These specify restrictive bounds for the types 2rational*, 2float* and so on. The bounds work on these types just the way they do on 2integer*. Exclusive and inclusive bounds make a useful difference here: 3(float (-4) (3)) *matches any float between -4 and 3, exclusive. No possible inclusive bounds could provide the same effect. 2(mod 1high*)* nonnegative integers less than 1high*. 1high* should be an integer. 2(mod)*, 2(mod *)* and plain 2mod* are allowed, but are equivalent to 2(integer 0)*. 2(signed-byte 1size*)* integers that fit into a byte of 1size* bits, of which one bit is the sign bit. 2(signed-byte 4)* is equivalent to 2(integer -8 7)*. 2(signed-byte *)* and plain 2signed-byte* are equivalent to 2integer*. 2(unsigned-byte 1size*)* nonnegative integers that fit into a byte of 1size* bits, with no sign bit. 2(unsigned-byte 3)* is equivalent to 2(integer 0 7)*. 2(unsigned-byte *)* and plain 2unsigned-byte* are equivalent to 2(integer 0)*. =Node: Simple Types for Arrays =Text: 3SIMPLE TYPES FOR ARRAYS 2array** all arrays. 2simple-array* arrays that are not displaced and have no fill pointers. (Displaced arrays are defined in 4(ARRAYS-1)Displaced Arrays* and fill pointers in 4(ARRAYS-1)Extra Features of Arrays*). 2vector* arrays of rank one. 2bit-vector* 2art-1b* arrays of rank one. 2string* strings; 2art-string* and 2art-fat-string* arrays of rank one. 2simple-bit-vector* bit vectors that are simple arrays. 2simple-string* strings that are simple arrays. 2simple-vector* simple-arrays of rank one, whose elements' types are unrestricted. This is not the same as 2(and vector simple-array)*! =Node: Restriction Types for Arrays =Text: 3RESTRICTION TYPES FOR ARRAYS 2(array 1element-type* 1dimensions*)** arrays whose rank and dimensions fit the restrictions described by 1dimensions* and whose nature restricts possible elements to match 1element-type*. The array elements condition has nothing to do with the actual values of the elements. Rather, it is a question of whether the array's own type permits exactly such elements as would match 1element-type*. If anything could be stored in the array that would not match 1element-type*, then the array does not match. If anything that would match 1element-type* could not be stored in the array, then the array does not match. For example, if 1element-type* is 2(signed-byte 4)*, the array must be an 2art-4b* array. An 2art-1b* array will not do, even though its elements all do match 2(signed-byte 4)*, because some objects such as the number 12 match 2(signed-byte 4)* but could not be stored in an 2art-1b* array. Likewise an 2art-q* array whose elements all happen to match 2(signed-byte 4)* will not do, since new elements such as 2nil* or 231 which fail to match could potentially be stored in the array. If 1element-type* is 2t*, the type to which all objects belong, then the array must be one in which any object can be stored: 2art-q* or 2art-q-list*. 2** as 1element-type* means ``no restriction''. Any type of array is then allowed, whether it restricts its elements or not. 1dimensions* can be 2**, an integer or a list. If it is 2**, the rank and dimensions are not restricted. If it is an integer, it specifies the rank of the array. Then any array of that rank matches. If 1dimensions* is a list, its length specifies the rank, and each element of 1dimensions* restricts one dimension. If the element is an integer, that dimension's length must equal it. If the element is *, that dimension's length is not restricted. 2(simple-array 1element-type* 1dimensions*)* the restrictions work as in 2(array 1element-type* 1dimensions*)*, but in addition the array must be a simple array. 2(vector 1element-type* 1size*)* 1element-type* works as above. The array must be a vector. 1size* must be an integer or *; if it is an integer, the array's length must equal 1size*. 2(bit-vector 1size*)* 2(simple-vector 1size*) (simple-bit-vector 1size*) (string 1size*) (simple-string 1size*)*These require the array to match type 2bit-vector*, 2simple-vector*, etc. This implicitly restricts the element type, so there is no point in allowing an 1element-type* to be given in the type specifier. 1size* works as in 2vector*. =Node: More Obscure Types =Text: 3MORE OBSCURE TYPES 2package** packages, such as 2find-package* might return. 2readtable* structures such as can be the value of 2readtable*. 2pathname* pathnames (instances of the flavor 2pathname*). 2hash-table* hash-tables (instances of the flavor 2hash-table*). 1flavor-name* instances of that flavor, or of any flavor that contains it. 1defstruct-name* named structures of that type, or of any structure that includes that one using 2:include*. =Node: Common Lisp Compatibility Types =Text: 3COMMON LISP COMPATIBILITY TYPES 2random-state** random-states. See 2random* (4(NUMBERS-2)Random Numbers*). This is actually a special case of using a defstruct name as a type specifier, but it is mentioned specifically because Common Lisp defines this type. 2common* All objects of types defined by Common Lisp. This is all Lisp objects except closures, entities, stack groups, locatives, instances, select-methods, and compiled and microcode functions. (A few kinds of instances, such as pathnames, are 2common*, because Common Lisp does define how to manipulate pathnames, and it is considered irrelevant that the Lisp Machine happens to implement pathnames using instances.) 2stream* Anything that looks like it might be a valid I/O stream. It is impossible to tell for certain whether an object is a stream, since any function with proper behavior may be used as a stream. Therefore, use of this type specifier is discouraged. It exists for the sake of Common Lisp. =Node: Combination Type Specifiers =Text: 3COMBINATION TYPE SPECIFIERS 2(member 1objects*)** any one of 1objects*, as compared with 2eql*. Thus, 2(member t nil x)* is matched only by 2t*, 2nil* or 2x*. 2(satisfies 1predicate*)* objects on which the function 1predicate* returns a non-2nil* value. Thus, 2(satisfies* 2numberp)* is equivalent as a type specifier to 2number* (though the system could not tell that this is so). 1predicate* must be a symbol, not a 2lambda*-expression. 2(and 1type-specs*...)* objecs that match all of the 1type-specs* individually. Thus, 2(and integer (satisfies oddp))* is the type of odd integers. 2(or 1type-specs*...)* objects that match at least one of the 1type-specs* individually. Thus, 2(or number array)* includes all numbers and all arrays. 2(not 1type-spec*)* objects that do not match 1type-spec*. =Node: User-Defined Type Specifiers =Text: 3USER-DEFINED TYPE SPECIFIERS deftype* 1type-name* 1lambda-list* 1body...* 1Macro* Defines 1type-name* as a type specifier by providing code to expand it into another type specifier--a sort of type specifier macro. When a list starting with 1type-name* is encountered as a type specifier, the 1lambda-list* is matched against the cdr of the type specifier just as the lambda-list of an ordinary 2defmacro*-defined macro is matched against the cdr of a form. Then the 1body* is executed and should return a new type specifier to be used instead of the original one. If there are optional arguments in 1lambda-list* for which no default value is specified, they get 2** as a default value. If 1type-name* by itself is encountered as a type specifier, it is treated as if it were 2(1type-name*)*; that is to say, the 1lambda-list* is matched against no arguments and then the 1body* is executed. So each argument in the 1lambda-list* gets its default value, and there is an error if they are not all optional. Example: 3(deftype vector (element-type size)* 3 `(array ,element-type (,size)))* could have been used to define 2vector*. 3(deftype odd-natural-number-below (n)* 3 `(and (integer 0 (,n)) (satisfies oddp)))* 3(typep 5 '(odd-natural-number-below 6)) => t* 3(typep 7 '(odd-natural-number-below 6)) => nil* =Node: Testing Types with Type Specifiers =Text: 3TESTING TYPES WITH TYPE SPECIFIERS type-of* 1object* Returns a type specifier which 1object* matches. Any given 1object* matches many different type specifiers, including 2t*, so you should not attempt to rely on knowing which type specifier would be returned for any particular object. The one actually returned is chosen so as to be informative for a human. Programs should generally use 2typep* rather than 2type-of*. See also 2data-type*, 4(PRIMOBJTYPE-1)Data Types*. 3typep* 1object* 1type-spec* 2t* if 1object* matches 1type-spec*. The fundamental purpose of type specifiers is to be used in 2typep* or other functions and constructs that use 2typep*. Examples: 3(typep 5 'number) => t* 3(typep 5 '(integer 0 7)) => t* 3(typep 5 'bit) => nil* 3(typep 5 'array) => nil* 3(typep "foo" 'array) => t* 3(typep nil 'list) => t* 3(typep '(a b) 'list) => t* 3(typep 'lose 'list) => nil* 3(typep 'x '(or symbol number)) => t* 3(typep 5 '(or symbol number)) => t* If the value of 1type-spec* is known at compile time, the compiler optimizes 2typep* so that it does not decode the argument at run time. In Maclisp, 2typep* is used with one argument. It returns a symbol describing the type of the object it is given. This is somewhat like what 2type-of* does, except in Maclisp the intention was to compare the result with 2eq* to test the type of an object. The Lisp Machine supports this usage of 2typep* for compatibility, but the returned symbol is a keyword (such as 2:list*, for conses) which makes it actually incompatible. This usage is considered obsolete and should be removed from programs. 3typecase* 1key-form* 1clauses...* 1Macro* Computes the value of 1key-form* and then executes one (or none) of the 1clauses* according to the type of the value (call it 1key*). Each clause starts with a type specifier, not evaluated, which could be the second argument to 2typep*. In fact, that is how it is used. The rest of the clause is composed of forms. The type specifiers of the clauses are matched sequentially against 1key*. If there is a match, the rest of that clause is executed and the values of the last form in it are returned from the 2typecase* form. If no clause matches, the 2typecase* form returns 2nil*. 2typecase*, like 2typep* is optimized carefully by the compiler. Note that 2t*, the type specifier that matches all objects, is useful in the last clause of a 2typecase*. 2otherwise* is also permitted instead of 2t* by special dispensation, with the same meaning. Example: 3(typecase foo* 3 (symbol (get-pname foo))* 3 (string foo)* 3 (list (apply 'string-append (mapcar 'hack foo)))* 3 ((integer 0) (hack-positive-integer foo))* 3 (t (princ-to-string foo))) etypecase* 1key-form* 1clauses...* 1Macro* Like 2typecase* except that an uncorrectable error is signaled if every clause fails. 2t* or 2otherwise* clauses are not allowed. 3ctypecase* 1place* 1clauses...* 1Macro* Like 2etypecase* except that the error is correctable. The first argument is called 1place* because it must be 2setf*'able (see 4(EVAL-2)setf*). If the user proceeds from the error, a new value is read and stored into 1place*; then the clauses are tested again using the new value. Errors repeat until a value is specified that makes some clause succeed. =Node: Coercion with Type Specifiers =Text: 3COERCION WITH TYPE SPECIFIERS coerce* 1object* 1type-spec* Converts 1object* to an ``equivalent'' object that matches 1type-spec*. Common Lisp specifies exactly which types can be converted to which other types. In general, a conversion that would lose information, such as turning a float into an integer, is not allowed as a coercion. Here is a complete list of types you can coerce to. 2complex* 2(complex 1type*)*Real numbers can be coerced to complex. If a rational is coerced to type 2complex*, the result equals the rational, and is not complex at all. This is because complex numbers with rational components are canonicalized to real if possible. However, if a rational is coerced to 2(complex float)* or 2(complex single-float)* then an actual complex number does result. It is permissible of course to coerce a complex number to a complex type. The real and imaginary parts are coerced individually to 1type* if 1type* is specified. 2short-float* 2single-float*Rational numbers can be coerced to floating point numbers and any kind of floating point number can be coerced to any other floating point format. 2float* Rational numbers are converted to 2single-float*'s; floats of all kinds are left alone. 2character* Strings of length one can be coerced to characters. Symbols whose print-names have length one can also be. An integer can be coerced to a character; this results in a character whose character code is the specified integer. 2list* Any vector can be coerced to type 2list*. The resulting list has the same elements as the vector. 2vector* or 2array* or any restricted array type. Any sequence (list or vector) can be coerced to any array or vector type. The new array has rank one and the same elements as the original sequence. If you specify a type of array with restricted element type, you may actually get an array which can hold other kinds of things as well. For example, the Lisp Machine does not provide anything of type 2(array symbol)*, but if you specify that, you will get an array which at least can hold symbols (but can hold other things as well). If an element of the original sequence does not fit in the new array, an error is signaled. 2t* Any object can be coerced to type 2t*, without change to the object. If the value of 1type-spec* is known at compile time, the compiler optimizes 2coerce* so that it does not decode the argument at run time. =Node: Comparing Type Specifiers =Text: 3COMPARING TYPE SPECIFIERS* Since a type describes a set of possible objects, it is possible to ask whether one type is contained in another type. Another way to say this is, is one type a 1subtype* of another? 3subtypep* 1type1* 1type2* 2t* if 1type1* is a subtype of 1type2*. The system cannot always tell whether 1type1* is a subtype of 1type2*. When 2satisfies* type specifiers are in use, this question is mathematically undecidable. Because of this, it has not been considered worthwhile to make the system able to answer obscure subtype questions even when that is theoretically possible. If the answer is not known, 2subtypep* returns 2nil*. Thus, 2nil* could mean that 1type1* is certainly not a subtype of 1type2*, or it could mean that there is no way to tell whether it is a subtype. 2subtypep* returns a second value to distinguish these two situations: the second value is 2t* if 2subtypep*'s first value is definitive, 2nil* if the system does not know the answer. Examples: 3(subtypep 'cons 'list) => t t* 3(subtypep 'null 'list) => t t* 3(subtypep 'symbol 'list) => nil t* 3(subtypep 'list 'number) => nil t* because not all lists are numbers (in fact, no lists are numbers). 3(subtypep 'number 'rational) => nil t* because not all numbers are rational. 3(subtypep '(satisfies foo) '(satisfies bar)) => nil nil* because the system does not attempt to figure out your code3.