Search code examples
lispcommon-lisplispworks

LISP - Replace values in a list


I have a list of nils (NIL NIL NIL NIL) and i need to add two X in place of the two first NILs, so it becomes (X X NIL NIL).

I have the following code:

(cons x (cons x (cons (cdr '(NIL NIL NIL NIL))nil)))

But this way it returns

(X X (NIL NIL))

Those parenteses need to be removed, and i don't know how. Can someone help me? Thanks


Solution

  • If you pass a list to the first argument of cons then you are making a nested list. First lets say we make your initial list and the symbol x variables:

    (defparameter *nils* '(nil nil nil nil))
    *nils* ; ==> (nil nil nil nil)
    
    (defparameter *x* 'x)
    *x* ; ==> x
    

    So how do we remove the two first. Well we can remove one with (cdr *nils*) so that means we can do it twice:

    (cdr (cdr *nils*))
    ; ==> (nil nil)
    

    Actually more than one car and cdr accessor has a shorthand upto 5 combinations. The shorthand is just starting with c and do the a/d's and end with r like this:

    (cddr *nils*)
    ; ==> (nil nil)
    

    Goodie, how do we add *x* in front of that? Well cons is defines as making an element in front of the second argument, thus (cons *x* (cddr *nils*)) will make(x nil nil). Again if you want to have anotherx` in front of that you do the same with the firt result:

    (cons *x* (cons *x* (cddr *nils*)))
    ; ==> (x x nil nil)
    

    Using list* is like nested cons with a tail in the end. Thus the above code can be replaced with:

    (list* *x* *x* (cddr *nils*))
    ; ==> (x x nil nil)
    

    Now replacing the variables the expression that was stored as their value (substitution method):

    (list* 'x 'x (cddr '(nil nil nil nil)))
    ; ==> (x x nil nil)