common-lisp

In common-lisp, how can I insert an element into a list in-place?


Two questions:

1.I want a function to insert an element inside a list in-place (in any position but the start of the list, see question 2 for the reason) such that:

CL> (defun insert-in-place (the-list after-position new-element) .... ) => ...
CL> (setf testy-list (list 'a 'b 'c 'd)) => ...  
CL> testy-list => ('A 'B 'C 'D)  
CL> (insert-in-place testy-list 1 'BOOOO) => ...  
CL> testy-list => ('A 'B 'BOOOO 'C 'D)

2.I think that inserting an element into the start of the list in-place is impossible through a function because the args are passed by value, so since the first cons cell of the list is passed, it is passed by value and it is a copy and so changing its car only changes a copy car, not the original, although the following cons cells are shared and change in place is possible. Am I correct?


Solution

  • 1) here it is:

    (defun insert-after (lst index newelt)
      (push newelt (cdr (nthcdr index lst))) 
      lst)
    (insert-after '(a c d) 0 'b)   => (A B C D)
    

    2) destructive modification of cons cells:

    (setf testy-list '(a bar))
    (defun modify (list)
      (setf (first list) 'foo))
    (modify testy-list)
    testy-list   => (FOO BAR)
    

    This sets the car of the first cons cell to 'foo.