Paralife
Paralife

Reputation: 6236

In common-lisp how is the relation between types defined?

While playing in Lisp i noticed the following:

(subtypep 'string '(array character)) ==> NIL, T
(subtypep '(array character) 'string) ==> NIL, T

while

(typep (make-string x) '(array character)) ==> T
(typep (make-array x :element-type :character) 'string) ==>T

for any value of x.

Which means that "subtypep" says that 'string and '(array character) are two distinct types while "typep" says that any instance of the one type is also an instance of the other (1)

Unless (1) is not true -please give example-, why does this happen? I find it difficult to grasp because I assume that a type cannot conceptually exist without its instances, that is, it is defined by its instances: It is the class (in the mathematical sense) of objects that have a specific set of properties. Is this correct?

EDIT: As correctly pointed (array character) is not necessarily a subtype of string, for the simple reason of the existence of multi-dimensinal arrays of characters. But I still cant imagine an instance of string that has not a type of (array character).

Upvotes: 4

Views: 395

Answers (4)

Paul Khuong
Paul Khuong

Reputation: 31

See http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)

Arrays in Common Lisp are mutable. Instead of attemping to pretend they're covariant or contravariant and adding complex dynamic checks, arrays in CL are invariant. Thus, unless they are the same, there is no subtyping relationship between (array character 1) and (array base-char 1). Programs shouldn't store non-base characters in the latter, and programs could read a non-base character from the former.

Array upgrading causes further confusions for newcomers. It helps to keep in mind that, while some compilers use type declarations for safety, their primary goal is performance. Typed arrays are mapped (upgraded) to a set of specially-handled array element types. These specialised array types must form a lattice (ensuring that we can sanely find the most specific specialised type), but there still no subtyping relationship.

Upvotes: 3

francogrex
francogrex

Reputation: 465

Try:

(subtypep '(vector nil) 'string)

in SBCL and other implementations to understand. The requirement of (vector nil) being a subtype of string follows from the standard, even if base-char and character are equivalent in an implementation.

Upvotes: 1

Doug Currie
Doug Currie

Reputation: 41180

It is an implemntaiton issue:

ccl e$ rlwrap ./dx86cl64
Loading ~/ccl-init.lisp
Welcome to Clozure Common Lisp Version 1.7-dev-r14614M-trunk  (DarwinX8664)!
? (subtypep 'string '(array character))
T
T
? 

Upvotes: 1

Vsevolod Dyomkin
Vsevolod Dyomkin

Reputation: 9451

Actually, this is some quirky thing in your implementation. (Possibly connected to some optimization).

For example in SBCL, if you (describe 'string), you'll get STRING names a primitive type-specifier: (undocumented). The interesting thing is that for base-string its the same, but:

(subtypep 'base-string 'array) => T
(subtypep 'base-string '(array base-char)) => T
(subtypep 'string 'array) => T
(subtypep 'string '(array character)) => NIL
(subtypep 'string '(array base-char)) => NIL
(subtypep 'string '(array standard-char)) => NIL
(subtypep 'string '(array extended-char)) => NIL

Upvotes: 1

Related Questions