Suppose we are talking about Common Lisp.
There is a macro (push item list)
that pushes the item
value to the top of the list
. In essence, it is equivalent to (setf list (cons item list))
.
Accordingly, in order to destructively insert an element into the list from the desired position, you need to take the list after this position, and replace it by inserting the element using push
.
True, there is one problem - the tail is most reasonable to get using nthcdr
, and this is a function, not an accessor (like car
or cdr
), and setf
so easy not to give it away. Just insert after the position is written - take cdr
from nthcdr
- you can feed it push
/ setf
, that's the thing with the ends:
(defun insert-after (item list index) "Destructively inserts 'item' into 'list' after 'index'." (push item (cdr (nthcdr index list))) list)
But to insert before the position will have a bit more cunning, the case with a zero index
must be specially processed. It will turn out to be a macra, and not a function (since it makes no sense to make a function (setf list …)
- the scope is different, see example 8.6.8 by reference):
(defmacro insert-at (item list index) "Destructively inserts 'item' into 'list' before 'index'." `(if (zerop ,index) (push ,item ,list) (insert-after ,item ,list (1- ,index))))
Checking:
(setf test-list '(abcd)) (insert-at 'z test-list 0) => (zabcd) (insert-at 'x test-list 5) => (zabcdx)
For deletion, the easiest way is probably to use setf
- for example, to remove the first list item, you need to replace the list itself with cdr
from it. To remove the second one, replace cdr
with cddr
. Etc.
If the logic of insertion is clear, then there should be no problems with the removal.