Common Lisp,从列表中删除元素破坏性

时间:2011-12-09 18:24:56

标签: lisp common-lisp

我有一个带有缺点的列表,例如 '((a . 3) (b . 2))。如果cons-pair中的第一个元素与var匹配,我想删除一个破坏性的cons-pair。如果列表中只有一个cons-pair或列表中的第一个cons-pair,则我的函数无法删除cons-pair。

(defun delete-bindings! (var symbol-table)
(cond
 ((endp symbol-table) '())
 ((eql var (caar symbol-table))
  (delete-bindings! var (cdr symbol-table)))
 (t (setf (cdr symbol-table) (delete-bindings! var (cdr symbol-table)))
   symbol-table))))

我错过了什么?

谢谢!

3 个答案:

答案 0 :(得分:2)

你的功能总是返回'(),我认为(不能确定,因为你没有显示整个事情)。

也许:

(defun delete-bindings! (var symbol-table)
  (cond
   ((endp symbol-table) '())
   ((eql var (caar symbol-table))
    (delete-bindings! var (cdr symbol-table)))
   (t (progn
        (setf (cdr symbol-table) (delete-bindings! var (cdr symbol-table)))
        symbol-table)))

附录:

您必须使用此功能的结果,而不仅仅取决于其副作用:

(setq *bindings* (delete-bindings! 'var *bindings*))

第二个附录

Loading ~/ccl-init.lisp
Welcome to Clozure Common Lisp Version 1.7-dev-r14406M-trunk  (DarwinX8632)!
? (defun delete-bindings! (var symbol-table)
  (cond
   ((endp symbol-table) '())
   ((eql var (caar symbol-table))
    (delete-bindings! var (cdr symbol-table)))
   (t (progn
        (setf (cdr symbol-table) (delete-bindings! var (cdr symbol-table)))
        symbol-table))))
DELETE-BINDINGS!
? (delete-bindings! 'a '((a . 3) (b . 2)))
((B . 2))
? 

如果您需要一个可能被破坏性修改的数据结构,并且所有对它的引用都已更新,那么您将需要另一级别的间接。

如,

(defvar *symbol-table* (cons 'bindings '((a . 3) (b . 2))))

(defun delete-bindings! (var symbol-table)
  (flet ((db! (var symbol-table) (cond
   ((endp symbol-table) '())
   ((eql var (caar symbol-table))
    (delete-bindings! var (cdr symbol-table)))
   (t (progn
        (setf (cdr symbol-table) (delete-bindings! var (cdr symbol-table)))
        symbol-table)))))
  (rplacd symbol-table (db! var (cdr symbol-table)))))

答案 1 :(得分:2)

函数不能修改它们作为参数获得的变量,它们总是接收变量的值而不是变量本身。相反,您可以使用DEFINE-MODIFY-MACRO

(define-modify-macro delete-bindings! (item)
  (lambda (symbol-table item)
    (remove item symbol-table :key #'car)))

答案 2 :(得分:0)

不是您问题的答案,但除非您是出于自我教学的目的,否则使用delete

会更容易

像(未经测试)的东西:

(defun delete-bindings! (var symbol-table)
    (delete var symbol-table :key #'car))