2017-02-13 18 views
1

В Paul Graham's book ANSI Common Lisp, обсуждая символ против манипуляций со строками, он говоритСимвол равенства

Символы можно сравнить в одном шаге с eql ...»

(P138). Здесь находятся два случая сравнения символов:

(setq x 3) 
3 
(setq a 'x) 
X 
(setq b 'x) 
X 
(eq a b) 
T 

Так, так как и точки б к тому же объекту символ, названный X, они eq Однако. , Это контрастирует с

(setq a (copy-symbol 'x)) 
#:X 
(setq b (copy-symbol 'x)) 
#:X 
(symbol-name a) 
"X" 
(symbol-name b) 
"X" 
(eq a b) 
NIL 
(eql a b) 
NIL 
(equal a b) 
NIL 
(equalp a b) 
NIL 

Теперь, а и б указывают на различные объекты символа, даже если они имеют один и тот же символ-имя и то же имя для печати. Мои вопросы:

  1. почему Грэм сказал eql, а не eq и
  2. во втором случае, почему а и б не по крайней мере equalp?
+1

EQ или EQL не делает никакой разницы при сравнении символов. copy-symbol возвращает новый, неинтерминированный символ. Таким образом, символы, созданные символом copy, не являются чем-то равным. Они всегда разные. –

+0

@Rainer Joswig Спасибо, что обратили мое внимание на то, что 'copy-symbol' не ставит символ. Как же использовать символ '(copy-symbol 'x t)' для копирования всех символьных функций X (кроме 'symbol-name') на другой интернированный символ Y? Или вам нужно сначала создать интернированный символ, а затем «setf» каждую функцию отдельно? – davypough

+0

'Как использовать один экземпляр (copy-symbol 'xt) для копирования всех символьных функций X (кроме имени-символа) на другой интернированный символ?' -> вы можете ставить новый и скопированный символ в другой пакет , –

ответ

4

eqleq?

eql «более предсказуем» в том смысле, что он менее зависим от реализации. например, Неоперативная числа (то есть, не- fixnum) может быть не- eq в некоторых реализациях и eq в других:

(= 1.5d0 1.5d0) 
=> T 
(eql 1.5d0 1.5d0) 
=> T 
(eq 1.5d0 1.5d0) 
=> T in some implementations, NIL in others 

почему не тождественно названные символы не equalp?

Вот что говорит спецификации :-)

Обратите внимание, что он нарушил правило:

Грубое правило заключается в том, что два объекта equal тогда и только тогда, когда их печатных представлений одинаковы.

Основным не-histerical Причиной этого является то, что символ, в то же время «атомный», по-прежнему имеют много багажа (например, переменной и функции привязки). IOW, a symbol - намного больше, чем его название.

Кроме того, один в целом ожидает, что equal формы оценки для equal значений, которые не могут быть в случае, если различные символы (с возможно различных привязок!) Оцениваются как equal.

Теперь, только различия между equal и equalp являются

  1. нечувствительны к регистру символов (и струнные) сравнение
  2. сравнение чисел с помощью =
  3. рекурсивно спускается в structure, array и hash-table.

Ни одно из этих изменений не влияет на «аналогичные правила оценки» выше, поэтому нет никаких оснований для equalp для сравнения символов на основе их имен.

Если вы хотите сравнить символы имен, вы можете использовать string=:

(eq '#:a '#:a) 
==> NIL 
(equalp '#:a '#:a) 
==> NIL 
(string= '#:a '#:a) 
==> T 
+0

Уберите эмпирические правила? 1. При сравнении чисел (любого типа) всегда используйте '=' (если вы не сравниваете представление чисел). 2. Два объекта являются «равными», если их печатные представления одинаковы (если только объекты не являются символами, хэш-таблицами, структурами или нестроковыми массивами). 3. Вы можете использовать 'string =' для сравнения имен символов, а также строк. – davypough

+0

@ davypough: точно. за исключением <3>, я бы сказал _use 'string =' для сравнения 'symbol', а также 'string'_. – sds