elisp 里 none consing/consing 该如何选择?

elisp里不少标准函数有 destructive(none consing),也有 copy(consing) 的,有的函数两种都有。我觉得写项目的时候这种最好还是统一,不然很容易不小心写出bug。

那么,在1)一个项目里,尤其是围绕一个中心的数据结构的项目里,应该选择哪种呢?

2)elisp会不会更适合某一个模式?

3)这两种模式在elisp里有没有什么特殊的特性(优缺点)?

(还是两种没啥区别,基本上是我庸人自扰?)

(伸个手)

别到处显式用列表就行。多用 defstruct 和 hash table。 就 elisp 这穷样,还是用列表吧(不穷,怎么老是讲穷人的哈希表云云嘛)

Copy(Consing) 没性能,要大量采用,除非是想玩 immutable data structure,然而 elisp 也没这个条件。

该怎么写就怎么写,怎么写自然就怎么写,不要把问题复杂化。

哪里有by value了

哪个又是by reference呢?

例子

所以到底是哪种效率比较高?列表还是hash table?我一般列表用alist。谢谢 :smile:

emasc本来性能一般,用copy好像的确不大好。

比如setcarsetcdr这种就是reference,append这种就是copy

哈希表存取时间在非最坏情况下与整个表大小无关,最坏情况(空间不够需要扩展)要复制整个表,另外要预先分配内存。

alist 存取时间和深度相关,另外额外占用列表长度数量的指针空间。

说人话就是,大量数据用哈希表,那种在十个 entry 以下的就用 alist 好了。

1 个赞

他们都是C函数 你要是也能写C函数 你就不用为这个问题发愁了

Nothing is true, everything is premitted. (要啥沒啥,爱咋咋地)​

(defun append (&rest lists)
  "Construct a new list by concatenating the list arguments"
  (if lists
    (let* ((head (cons nil nil))
           (tail head))
      (do* ()
           ((null lists) (cdr head))
        (let* ((list (pop lists)))
          (if (null lists)
            (rplacd tail list)
            (dolist (element list)
                (setq tail (cdr (rplacd tail (cons element nil)))))))))))

(defun setcar (x y) (setf (car x) y))
1 个赞
(setq zxc '(56 78))

(macroexpand '(setf (car zxc) 78)) ==> (let* ((v zxc)) (setcar v 78))

哪有什么by value 都是reference(C函数才能产生新的reference)

1 个赞

重点在 copy。题主不懂名词望文生意拿来乱用罢了。

另外我太懒了,不想在抄一个不用 setcarsetf(也太长了,大概几百来行)

链接 有 也行

本来想说修改原参数,感觉好像不对。没学过想不出来词啊 :joy:

ccl 和 elisp 不一样的吧

除了有个利用 method 的 dispatch 有点难搞(其实也不难搞),剩下的都可以用 cl-lib 套。我本地还有个用 Lisp Machine Lisp 写的 SETF,和 Emacs Lisp 更接近,就是因為 license 不能隨便发。