В общих чертах, как определяется связь между типами? - PullRequest
4 голосов
/ 20 октября 2011

Во время игры в Лисп я заметил следующее:

(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

для любого значения x.

Что означает, что «subtypep» говоритчто 'string и' (символ массива) являются двумя разными типами, в то время как typep говорит, что любой экземпляр одного типа также является экземпляром другого (1)

Если (1) не соответствует действительности - пожалуйста, приведите пример - почему это происходит?Мне трудно понять, потому что я предполагаю, что тип не может концептуально существовать без его экземпляров, то есть он определяется его экземплярами: это класс (в математическом смысле) объектов, которые имеют определенный набор свойств.Это правильно?

РЕДАКТИРОВАТЬ: Как правильно указано, (array character) не обязательно является подтипом string по простой причине существования многомерных массивов символов.Но я все еще не могу представить себе экземпляр string, который не имеет типа (array character).

Ответы [ 4 ]

3 голосов
/ 22 октября 2011

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

Массивы в Common Lisp изменчивы. Вместо того, чтобы делать вид, что они ковариантны или контравариантны, и добавлять сложные динамические проверки, массивы в CL инвариантны. Таким образом, если они не одинаковы, между типами (array character 1) и (array base-char 1) нет подтипов. Программы не должны хранить неосновные символы в последнем, и программы могут читать неосновные символы из первого.

Модернизация массива вызывает дальнейшее замешательство для новичков. Это помогает помнить, что, хотя некоторые компиляторы используют декларации типов для безопасности, их основная цель - производительность. Типизированные массивы отображаются (обновляются) на набор специально обработанных типов элементов массива. Эти специализированные типы массивов должны образовывать решетку (гарантирующую, что мы сможем найти наиболее конкретный специализированный тип), но при этом отношения подтипов по-прежнему отсутствуют.

1 голос
/ 21 октября 2011

Это вопрос реализации:

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
? 
1 голос
/ 22 октября 2011

Попробуйте:

(subtypep '(vector nil) 'string)

в SBCL и других реализациях для понимания. Требование, чтобы (вектор ноль) был подтипом строки, следует из стандарта, даже если в реализации эквивалентны base-char и символ.

1 голос
/ 20 октября 2011

На самом деле, это странная вещь в вашей реализации.(Возможно, связано с некоторой оптимизацией).

Например, в SBCL, если вы (describe 'string), вы получите STRING names a primitive type-specifier: (undocumented).Интересно, что для base-string то же самое, но:

(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
...