Elisp:如何将元素添加到列表中

8
有没有一种方法在elisp中向列表推回元素?
我找到的最接近的方法是
(add-to-list 'myList myValue t) ;; t tells it to put to back of the list

然而问题在于,`add-to-list` 函数会强制要求唯一性。另一种选择是使用 `(push 'myList myVal)`,但这只能将值推入列表的前端。我曾尝试使用 `(cons myList myVal)`,但据我所知,它返回的不是列表。
目前工作的唯一方法是:
(setq myList (append myList (list myVal)))

但那个语法很丑陋,感觉相当复杂,只是为了完成简单的操作。有没有更快的方法将元素推到列表的末尾?显然这是可能的,就像在(add-to-list)中看到的那样,但不强制唯一性,是否有某种方法可以做到呢?换句话说,像C++和List类中的老式push-back函数一样的好用的功能。

1
作为后续问题,为什么elisp如此简洁?我觉得它只有最基本的工作所需。这背后是否有某种哲学思想? - Cameron
它是一种Lisp语言,例如一种可扩展的语言。如果有什么让你烦恼的东西,你总可以编写一个宏并改变其行为。 - hajovonta
2个回答

10

Lisp列表与其他语言中的“列表”

Lisp列表是由cons单元链(“链表”)构成的,不像C语言中那样是专门的顺序容器,也不像Perl和Python中一样是奇怪的列表和向量混合体。

这种优美的方法允许将相同的方法应用于代码数据,从而创建出可编程的编程语言。

Lisp没有“push-back”函数的原因是:

  • 它不需要它 :-)
  • 它没有很好的定义

无需

在列表末尾添加项的时间复杂度与列表长度成线性关系,因此,在处理聚合时,标准模式是在迭代时使用push,在完成后使用nreverse

没有很好的定义

add-to-list接受symbol作为参数是有原因的(这使得它对编程来说毫无用处)。

当你添加到一个空列表时会发生什么?你需要修改存储列表的位置

当列表与另一个对象共享结构时会发生什么?如果你使用的是

(setq my-list (nconc my-list (list new-value)))

所有其他对象也会被修改。

如果您按照您建议的方式编写,

(setq my-list (append my-list (list new-value)))

每次添加时,您将分配(length my-list)个单元。


0

试试这个:

(defun prueba ()
  (interactive)
  (let ((mylist '(1 2 3)))
    (message "mylist -> %s" mylist)
    (add-to-list 'mylist 1 t)
    (message "mylist -> %s" mylist)
    (setq mylist '(1 2 3))
    (add-to-list 'mylist 1 t '(lambda (a1 a2) nil))
    (message "mylist -> %s" mylist)
    ))

添加一个比较函数,该函数始终将 nil 作为第四个参数返回给 add-to-list,这样您就可以添加重复项。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接