hemma
hemma

Reputation: 13

Common Lisp, remove element from list destructive

I have a list with cons-pairs, e.g. '((a . 3) (b . 2)). I want to remove a cons-pair destructive if the first element in the cons-pair matches var. My function cannot remove the cons-pair if there is only one cons-pair in the list or if it is first in the list.

(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))))

What am I missing?

Thanks!

Upvotes: 1

Views: 4601

Answers (3)

Doug Currie
Doug Currie

Reputation: 41170

Your function is always returning '(), I think (can't be sure since you didn't show the whole thing).

Perhaps:

(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)))

Addendum:

You must use the result of this function, not simply depend on its side effects:

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

Second addendum

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))
? 

If you need a data structure that may be destructively modified with all references to it updated, you'll need another level of indirection.

E.g.,

(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)))))

Upvotes: 2

Rörd
Rörd

Reputation: 6681

Functions cannot modify a variable that they get as argument, they always receive the variable's value instead of the variable itself. Instead, you can use DEFINE-MODIFY-MACRO:

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

Upvotes: 1

JB.
JB.

Reputation: 42094

Not an answer to your question, but unless you're doing this for self-teaching purposes, it would be easier with delete

Something like (untested):

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

Upvotes: 0

Related Questions