LISP - Replace values in a list

1.2k Views Asked by At

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

2

There are 2 best solutions below

0
On BEST ANSWER

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)
0
On
(list* X X (nthcdr 2 your-list))

The function NTHCDR returns the list with two first elements dropped & the function LIST* returns a new list appending specified items at the front. Observe that thus you obtain a new list rather then modify the original one. If you really want to modify the original list (this may very well be a bad idea, proceed with caution), you can just make the assignment:

(setf (first your-list) 'X)
(setf (second your-list) 'X)

Modifying a list like this may result in modifications of seemingly unrelated data. It is not compatible with the quoted literal list, anyway.