是否有像 "cl-every" 这样的 elisp 函数在不等长的列表中返回 nil?



我想使用(cl-every #'eq list1 list2)比较 elisp 中的两个列表。但是,如果其中一个列表比另一个列表长,这可能会返回t,我不希望这样。我可以在列表中调用length,但是我遍历每个列表两次,这是不必要的低效。有没有像cl-every这样的函数也可以检查相等的长度?

OOTB

我不认为有这样的功能 OOTB。

自己动手

我认为实现一个并不难,只需修改cl-every.

长度

请注意,length是用 C 实现的,除非您的列表很大,否则不会明显影响性能:

(defun list-elements-eq (l1 l2)
(and (= (length l1)
(length l2))
(every #'eq l1 l2)))

平等

您还可以将equal用于列表:由于equal从测试eq开始,因此它将是一个比您想要的更弱的关系。

请注意,在 Common Lisp 中,equal可能不会终止于循环结构。 Emacs Lisp "更智能":它可以检测 cicularity:

(setq x (list 1))
(setcdr x x)
(setq y (list 1))
(setcdr y y)
(eq x y)
(equal x y)
Debugger entered--Lisp error: (circular-list #1=(1 . #1#))
equal(#1=(1 . #1#) #2=(1 . #2#))

(可以说,它应该返回t(。

Common Lisp

一般来说,Common Lisp 是"繁重工作"的更好语言。

如果你的列表很大,你可能想使用它而不是Emacs Lisp:

(defun list-elements-eq (l1 l2)
(if (endp l1)
(endp l2)
(and (not (endp l2))
(eq (pop l1) (pop l2))
(list-elements-eq l1 l2))))

这是尾递归的,任何像样的 CL 都会优化递归(可能取决于optimize设置(。

你不想在 ELisp 中使用深度递归(参见为什么 Emacs lisp 中没有尾递归优化,而不是像其他方案一样?(。

最新更新