Возможно наиболее важными предикатами в Lisp’е это предикаты, которые различают типы данных. То есть позволяют узнать принадлежит ли заданный объект данному типу. Также предикаты могут сравнивать два спецификатора типов.
Если тип данных рассматривать, как множество все объектов, принадлежащих этому типу, тогда функция typep проверяет принадлежность множеству, тогда как subtypep — принадлежность подмножеству.
typep является предикатом, который истинен, если объект object принадлежит типу type, и ложен в противном случае. Следует отметить, что объект может принадлежать нескольким типам, так как один тип может включать другой. type может быть любым спецификатором типа, описанным в главе 4, за исключением того, что он не может быть или включать список спецификатор типа, у которого первый элемент равен function или values. Спецификатор формы (satisfies fn) обрабатывается просто как применение функции fn к объекту object (смотрите funcall). Объект object принадлежит заданному типу, если результат не равен nil.
X3J13 voted in January 1989 to change typep to give specialized array and complex type specifiers the same meaning for purposes of type discrimination as they have for declaration purposes. Of course, this also applies to such type specifiers as vector and simple-array (see section 4.5). Thus
in the first edition asked the question, Is foo an array specialized to hold bignums? but under the new interpretation asks the question, Could the array foo have resulted from giving bignum as the :element-type argument to make-array?
Аргументы должны быть спецификаторами типов, но только теми, которые могут использоваться и для typep. Два спецификатора типа сравниваются. Данный предикат истинен, если тип type1 точно является подтипом типа type2, иначе предикат ложен. Если результат nil, тогда тип type1 может быть, а может и не быть подтипом типа type2 (иногда это невозможно определить, особенно когда используется тип satisfies). Второе возвращаемое значение указывает на точность результата. Если оно является истиной, значит первое значение указывает на точную принадлежность типов. Таким образом возможны следующие комбинации результатов:
X3J13 voted in January 1989 to place certain requirements upon the implementation of subtypep, for it noted that implementations in many cases simply “give up” and return the two values nil and nil when in fact it would have been possible to determine the relationship between the given types. The requirements are as follows, where it is understood that a type specifier s involves a type specifier u if either s contains an occurrence of u directly or s contains a type specifier w defined by deftype whose expansion involves u.
In addition, X3J13 voted to clarify that in some cases the relationships between types as reflected by subtypep may be implementation-specific. For example, in an implementation supporting only one type of floating-point number, (subtypep ’float ’long-float) would return t and t, since the two types would be identical.
Note that satisfies is an exception because relationships between types involving satisfies are undecidable in general, but (as X3J13 noted) and, or, not, and member are merely very messy to deal with. In all likelihood these will not be addressed unless and until someone is willing to write a careful specification that covers all the cases for the processing of these type specifiers by subtypep. The requirements stated above were easy to state and probably suffice for most cases of interest.
X3J13 voted in January 1989 to change subtypep to give specialized array and complex type specifiers the same meaning for purposes of type discrimination as they have for declaration purposes. Of course, this also applies to such type specifiers as vector and simple-array (see section 4.5).
If A and B are type specifiers (other than *, which technically is not a type specifier anyway), then (array A) and (array B) represent the same type in a given implementation if and only if they denote arrays of the same specialized representation in that implementation; otherwise they are disjoint. To put it another way, they represent the same type if and only if (upgraded-array-element-type ’A) and (upgraded-array-element-type ’B) are the same type. Therefore
is true if and only if (upgraded-array-element-type ’A) is the same type as (upgraded-array-element-type ’B).
The complex type specifier is treated in a similar but subtly different manner. If A and B are two type specifiers (but not *, which technically is not a type specifier anyway), then (complex A) and (complex B) represent the same type in a given implementation if and only if they refer to complex numbers of the same specialized representation in that implementation; otherwise they are disjoint. Note, however, that there is no function called make-complex that allows one to specify a particular element type (then to be upgraded); instead, one must describe specialized complex numbers in terms of the actual types of the parts from which they were constructed. There is no number of type (or rather, representation) float as such; there are only numbers of type single-float, numbers of type double-float, and so on. Therefore we want (complex single-float) to be a subtype of (complex float).
The rule, then, is that (complex A) and (complex B) represent the same type (and otherwise are disjoint) in a given implementation if and only if either the type A is a subtype of B, or (upgraded-complex-part-type ’A) and (upgraded-complex-part-type ’B) are the same type. In the latter case (complex A) and (complex B) in fact refer to the same specialized representation. Therefore
is true if and only if the results of (upgraded-complex-part-type ’A) and (upgraded-complex-part-type ’B) are the same type.
Under this interpretation
must be true in all implementations; but
is true only in implementations that do not have a specialized array representation for single-float elements distinct from that for float elements in general.
Следующие предикаты осуществляют проверку определённых типов данных.
null истинен, если аргумент является (), иначе является ложью. Похожая операция производится not, однако not используется для отрицания булевых значение, тогда как null используется для проверки того, пустой ли список. Таким образом программист может выразить свои намерения, выбрав нужное имя функции.
symbolp истинен, если её аргумент является символом, в противном случае ложен.
Предикат atom истинен, если аргумент не является cons-ячейкой, в противном случае ложен. Следует отметить (atom ’()) являет истиной, потому что () ≡nil.
Предикат consp истинен, если его аргумент является cons-ячейкой, в противном случае ложен. Следует отметить, пустой список не является cons-ячейкой, так (consp ’()) ≡ (consp ’nil) ⇒ nil.
listp истинен, если его аргумент является cons-ячейкой или пустым списком (), в противном случае ложен. Она не проверяет является ли «список Ъ (true list)» (завершающийся nil) или «с точкой (dotted)» (завершающийся не-null атомом).
numberp истинен, если аргумент это любой вид числа, в противном случае ложен.
integerp
истинен, если аргумент целое число, в противном случае ложен.rationalp истинен, если аргумент рациональное число (дробь или целое), в противном случае ложен.
floatp истинен, если аргумент число с плавающей точкой, в противном случае ложен.
realp истинна, если аргумент является действительным числом, иначе ложна.
complexp
истинен, если аргумент комплексное число, в противном случае ложен.bit-vector-p истинен, если аргумент битовый вектор, иначе ложен.
vectorp истинен, если аргумент простой общий вектор, иначе ложен.
simple-string-p истинен, если аргумент простая строка, иначе ложен.
simple-bit-vector-p истинен, если аргумент простой битовый вектор, иначе ложен.
packagep истинен, если аргумент является пакетом, иначе является ложью.
Типы cons и symbol непересекаются с типом function. functionp является ложной для символов и списков.
compiled-function-p истинен, если аргумент — скомпилированный объект кода, иначе ложен.
Смотрите также standard-char-p, string-char-p, streamp, random-state-p, readtablep, hash-table-p и pathnamep.