Some old code looked like this:
(progn
(push new-item list-of-items)
(delete old-item list-of-items) `
list-of-items)
I changed it to:
(progn
(delete old-item list-of-items)
(push new-item list-of-items)
list-of-items)
Because delete works on a shorter list, it is likely to be faster.
But now, sometimes old-item stays in list-of-items. What's wrong?
* * *
Dear Mighty,
Well, the macro call
(push new-item list-of-items)
is equivalent to
(setf list-of-items (cons new-item list-of-items)).
Therefore, it will update list-of-items correctly.
Delete is a destructive function meaning it can modify its argument but
you cannot depend on it. During the function call, delete will locate the
cons cell containing old-item, if it is not the first cons cell of
list-of-items then it will "surgically" remove it from the list leaving
list-of-items modified. However, if it is the first cons cell, delete will
just return the cdr of list-of-items, leaving list-of-items unmodified.
The correct code is:
(progn
(setf list-of-items (delete old-item list-of-items))
(push new-item list-of-items)
list-of-items)
The moral is: don't count on destructive functions for doing the intended
side effect on the arguments but use the result instead.
Oh, why did the old code work? I leave it to you.
Patrick.
|