我有一个带有缺点的列表,例如 '((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))))
我错过了什么?
谢谢!
答案 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))