Subject: Re: problem with delete From: Erik Naggum <erik@naggum.net> Date: 2000/10/02 Newsgroups: comp.lang.lisp Message-ID: <3179481728635665@naggum.net> * rolni104@ida.liu.se (Roland Nilsson) | I'm having a weird problem with (delete item list). Nope. You're having a minor problem understanding how lists are represented. You're also having a minor misunderstanding of what it means for a Lisp function be destructive and have side effects. delete is one of those functions that have side effects as a side effect. Its main effect is to return a list as per specification. (The streams functions have side effects as their main effect...) | Consider: | | (setq foo '(1 2 3 4 5)) foo is a pointer to a cons cell containing 1 and a pointer to a cons cell containing 2 and a pointer to a cons cell containing 3 and a pointer to a cons cell containing 4 and a pointer to a cons cell containing 5 and nil. | (when (my-test-for-deletion) | (delete 1 foo)) | | Ok, here delete should modify foo, so that | | foo => (2 3 4 5) delete does not modify variables, _ever_. That would be the macro setq/setf (or any of the other macros that use setq/setf). delete modifies the structure of the internal pointers in the list structure. Say you delete 3 from the list. foo is a pointer to a cons cell containing 1 and a pointer to a cons cell containing 2 and a pointer to a cons cell containing 4 and a pointer to a cons cell containing 5 and nil. As a special case, if the first element of a list is to be deleted, which pointer needs to be modified in order to reflect the missing element? Hint: _not_ one of the poiners in the list structure. | Also, the delete clause should evaluate to this. For me, delete | *does* return this result, but it *does not* modify the list, i.e. Bingo! Use the value it returns, then. Never use delete for its side effect (unless you know exceptionally well what you're doing). | (delete 1 foo) => (2 3 4 5), but still | foo => (1 2 3 4 5) Of course. foo points to the cons cell that contains 1 and a pointer to the cons cell that contains 2 and ... For delete to work the way you seem to want, it would have to rearrange the entire top-level list structure. | For example, (setf foo (delete 1 foo)) does what's intended. It's | like delete is acting like remove, non-destructive, in this case. Um, no. "Destructive" means that while building the result it is free to reuse the resources that were used in one (or more) of the arguments. (let ((foo (list 1 2 3 4 5))) (values (eq (cdr foo) (remove 1 foo)) (eq (cdr foo) (delete 1 foo)))) This should return as two values nil and t. Explain why. Why don't you write your own delete function that behaves the way you want, then try to understand how delete has been implemented, and argue for both designs and implementations? #:Erik -- If this is not what you expected, please alter your expectations.