Lisp 关联列表错误

Lisp association list error

我编写了将 cons 单元格插入关联列表的代码。 比如有关联表

((1 . a) (3 . c) (4 . d))

我想插入 cons 单元格 (2 . b) 然后这个程序生成

((1  a) (2 . b) (3 . c) (4 . d))

但是我的代码引发了异常

(car L) should be a lambda expression

下面是我的代码

(defun INSERTCELL (R L)
  (cond ((< (car L) (car R)) cons((car L) INSERTCELL(R (cdr L))))
        (t cons(R L))))

R(2 . b)L((1 . a) (3 . c) (4 . d))所以R应该插入到L.

Lisp 中的函数调用是 cons cells:

(cons 1 2)
==> (1 . 2)

如果您修复代码:

(defun insertcell (R L)
  (cond ((< (caar L) (car R)) (cons (car L) (insertcell R (cdr L))))
        (t (cons R L))))

有效:

(insertcell '(2 . b) '((1 . a) (3 . c) (4 . d)))
==> ((1 . A) (2 . B) (3 . C) (4 . D))

请注意,您还需要执行 (caar L),而不是 (car L),因为 L 是一个列表,因此要访问第一个键,您需要调用 car 两次.

takes care of the typographical issue in your code, as well as some of the other bugs. That said, I think it's worth noting that there might be other ways to do this. First, association lists don't have to be stored in order. If you don't need yours to be in order, then you can simply use acons 将新元素添加到开头:

(let ((alist '((1 . a) (3 . c) (4 . d))))
  (acons 2 'b alist))
;=> ((2 . B) (1 . A) (3 . C) (4 . D))

如果您确实需要维护排序条件,一种选择是使用上述方法,然后 sort the list afterward. That's probably a bit overkill, though, since you already know that the association list is sorted, and you only need to put the new element in its place. To that end, you can use the built in merge 函数合并您的关联列表和新元素(通过将其包装在列表中,所以它是一个元素的关联列表):

(let ((alist (copy-list '((1 . a) (3 . c) (4 . d))))
      (new (list (cons 2 'b))))
  (merge 'list alist new '< :key 'car))
;=> ((1 . A) (2 . B) (3 . C) (4 . D))

(let ((alist '((1 . a) (3 . c) (4 . d))))
  (merge 'list (copy-list alist) (copy-list '((2 . b)))
         '< :key 'car))
;=> ((1 . A) (2 . B) (3 . C) (4 . D))

注意 merge 是破坏性的(也就是说,它允许修改它的参数),这就是我在这里使用 copy-list 来获取新数据的原因。在您的情况下,由于您可能正在逐步构建列表,所以它可能没问题,与保存结果一样长。例如,

(defun insert-cell (key value alist)
  (merge 'list alist (list (cons key value))
         '< :key 'car))
(let ((alist '()))
  (setf alist (insert-cell 1 'a alist))
  (setf alist (insert-cell 4 'd alist))
  (setf alist (insert-cell 3 'c alist))
  (setf alist (insert-cell 2 'b alist))
  alist)
;=> ((1 . A) (2 . B) (3 . C) (4 . D))