公共Lisp符号相等



在互联网上的大多数例子中,符号平等是直接的:

(eq 'sym 'sym)
t

在我的程序中,我想比较自定义包中的符号:

(defpackage #:my-package
(:use    #:common-lisp)
(:export #:my-function))
(in-package #:my-package)
(defun my-function (value)
(cond
((eq value 'sym)
(format t "SYM: YES~%"))
(t
(format t "SYM: NO~%"))))
(in-package #:common-lisp)
(my-package:my-function 'sym)

但当执行此代码时,它会显示:

SYM: NO

这两个符号似乎不同:

(eq 'sym 'my-package::sym)
nil

原因似乎很容易理解,一个符号在一个给定的包中不等于一个相同名称的符号在另一个包中。很公平!但是,不管包装如何,比较两个符号的习惯用法是什么?

我们应该首先将其转换为字符串并比较字符串吗?

(defpackage #:my-package
(:use    #:common-lisp)
(:export #:my-function))
(in-package #:my-package)
(defun my-function (value)
(cond
((string= (symbol-name value) "SYM")
(format t "SYM: YES~%"))
(t
(format t "SYM: NO~%"))))
(in-package #:common-lisp)
(my-package:my-function 'sym)

结果是更好的,但有一个明显的问题,关于性格的情况。

如何检查两个符号是否相同,无论其包装如何?

通常的习惯用法是string=,它比较符号的名称而不考虑身份。

例如:

(eq 'x:a 'y:a) => nil
(string= 'x:a 'y:a) => t

我想你对"是同一个符号"的含义感到困惑。

两个符号是相同的符号iff它们是eq,这意味着如果它们不是eq,它们就不是相同的符号。特别地,如果两个符号具有不同的主包(再次:不是eq(,则它们不是相同的符号。

如果您想知道两个符号是否具有相同的名称,那么只需将它们的symbol-name作为字符串进行比较。但是仅仅具有相同名称的两个符号不一定是相同的符号(例如(eq '#:foo '#:foo)为假(。

在某些情况下,知道两个符号是否具有相同的名称是有用的(例如,loop宏必须这样做,以便(loop for ...)(loop :for ...)的意思相同(,但这些情况相当罕见。

如果你想知道两个符号是否有相同的名称,你很可能应该使用字符串。

如果你真正想知道的是从不同包访问的两个符号是否真的是同一个符号(比如(eq 'x:foo 'y:foo)(,那么eq是合适的测试,了解包系统也有帮助。

相关内容

  • 没有找到相关文章

最新更新