【问题标题】:Symbol equality符号相等
【发布时间】:2017-07-02 01:24:24
【问题描述】:

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

所以,由于ab 指向同一个符号对象,名为"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

现在,ab 指向不同的 symbol 对象,即使它们具有相同的 symbol-name 和相同的打印名称。我的问题是:

  1. 为什么格雷厄姆说eql而不是eq,以及
  2. 在第二种情况下,为什么ab 至少不是equalp

【问题讨论】:

  • EQ 或 EQL 在比较符号时没有区别。 copy-symbol 返回一个新的、非驻留的符号。因此,由 copy-symbol 创建的符号不等于任何东西。它们总是不同的。
  • @Rainer Joswig 感谢您提醒我注意copy-symbol 不实习符号这一事实。那么如何使用(copy-symbol 'x t) 将X 的所有符号特征(symbol-name 除外)复制到另一个实习符号Y?还是您必须先创建一个实习符号,然后分别setf 每个功能?
  • How then does one use (copy-symbol 'x t) to copy to copy all the symbol features of X (except symbol-name) to another interned symbol?-> 您可以将新的和复制的符号实习到其他包中。

标签: common-lisp symbols


【解决方案1】:

eql 超过 eq?

eql 是“更可预测的”,因为它不太依赖于实现。 例如,非立即数(即, 非fixnums) 可以是非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 reason 是那个符号,而 “原子”,仍然带有许多包袱(例如,变量和函数 绑定)。 IOW,symbol 是 远不止它的名字。

此外,人们通常期望equal 表单评估为 equal 值,如果不同的符号(与 可能不同的绑定!)被评估为equal

现在,equalequalp 之间的唯一区别是

  1. 不区分大小写的字符(和字符串)比较
  2. 使用=比较数字
  3. 递归下降到 structure, array,和 hash-table

这些变化都不会影响上面的“相似评估规则”, 所以equalp 没有理由根据 他们的名字。

如果你想按名称比较符号,你可以 使用string=:

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

【讨论】:

  • 取消经验法则? 1. 比较数字(任何类型)时,请始终使用=(除非您要比较数字的表示形式)。 2. 两个对象是equal,如果它们的打印表示相同(除非对象是符号、哈希表、结构或非字符串数组)。 3.您可以使用string=来比较符号名称以及字符串。
  • @davypough:准确地说。除了 我会说 使用string= 来比较symbols 和strings
猜你喜欢
  • 2014-05-09
  • 1970-01-01
  • 2012-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多