6

emacs lisp 是否具有提供唯一对象标识符(例如内存地址)的功能?Python has id(),它返回一个整数,保证在当前存在的对象中是唯一的。省略号呢?

4

3 回答 3

7

我知道想要一个函数的唯一原因id()是比较对象,并确保它们只有在它们相同时才比较相等(如在相同的内存位置)。在 Lisps 中,这与 Python 中的做法有些不同:

在大多数 lisp 中,包括 elisp,有几种不同的相等概念。最昂贵和最弱的等价物是equal. 这不是您想要的,因为如果两个列表(例如)具有相同的元素(使用 递归测试),则它们是相等的equal。像这样

(equal (list 1 2) (list 1 2)) => T

是真的。在频谱的另一端是eq,它测试“身份”而不是平等:

(eq (list 1 2) (list 1 2)) => NIL

这就是你想要的,我想。

因此,Python 似乎通过提供一个相等性测试来工作,然后提供一个函数,为每个对象提供一个内存位置,然后可以将其作为整数进行比较。另一方面,在 Elisp(至少也包括 Common Lisp)中,“平等”的含义不止一个。

请注意,还有“eql”,位于两者之间。

(编辑:我的原始答案可能不够清楚,为什么区分eqequal可能解决了原始海报所遇到的问题)

于 2012-08-25T18:08:03.230 回答
4

据我所知,Emacs Lisp 中没有这样的功能。如果您只需要相等,请使用eq,它在后台执行指针比较。如果您需要可打印的唯一标识符,请gensymcl包中使用。如果您需要一个唯一标识符作为数据结构中的索引,请使用gensym(或维护您自己的唯一 ID —gensym更简单且不易出错)。

一些语言将唯一的 id 烘焙到每个对象中,但这需要付出代价:每个对象都需要额外的内存来存储 id,或者 id 是从对象的地址派生的,这样就无法修改地址。Python 选择付出代价,Emacs 选择不付出。

于 2012-08-26T20:05:04.473 回答
4

我提出这个问题的全部意义在于,我正在寻找一种方法来区分具有相同名称的不同符号的印刷表示。多亏了 elisp 手册,我发现了变量print-gensym,当非 时nil,它会导致#:被添加到打印的未执行符号之前。此外,如果同一个调用print多次打印相同的非实习符号,它将#N=用`#N#标记第一个符号和后续符号。这正是我正在寻找的那种功能。例如:

(setq print-gensym t)
  ==> t
(make-symbol "foo")
  ==> #:foo
(setq a (make-symbol "foo"))
  ==> #:foo
(cons a a)
  ==> (#1=#:foo . #1#)
(setq b (make-symbol "foo"))
  ==> #:foo
(cons a b)
  ==> (#:foo . #:foo)

#:符号也适用于read

(setq a '#:foo)
  ==> #:foo
(symbol-name a)
  ==> "foo"

请注意'on '#:foo--#:表示法是符号文字。如果没有',则评估 uninterned 符号:

(symbol-name '#:foo)
  ==> "foo"
(symbol-name #:foo)
 ==> (void-variable #:foo)
于 2012-08-27T01:44:25.750 回答