The behavior you observe is correct and expected:
psetf returns nil
and mapcar places the return value
into the return list, so when num is 0, you get there nil,
and when it is 1, you get the original cell.
Easily fixed:
(mapcar (lambda (x)
(when (zerop (random 2))
(psetf (cdr x) (car x) (car x) (cdr x)))
x)
'((B . 21) (O . 24) (P . 15) (R . 47) (K . 49)))
==> ((B . 21) (24 . O) (P . 15) (47 . R) (K . 49))
actually, CL has a macro rotatef
just for your case:
(mapcar (lambda (x)
(when (zerop (random 2))
(rotatef (cdr x) (car x)))
x)
'((B . 21) (O . 24) (P . 15) (R . 47) (K . 49)))
==> ((21 . B) (O . 24) (15 . P) (R . 47) (K . 49))
Finally, please note that modifying quoted data is a very bad idea:
(defparameter *alist-0* '((B . 21) (O . 24) (P . 15) (R . 47) (K . 49)))
(defparameter *alist-1*
(mapcar (lambda (x)
(when (zerop (random 2))
(rotatef (cdr x) (car x)))
x)
*alist-0*))
(eq *alist-0* *alist-1*)
==> nil
(equal *alist-0* *alist-1*)
==> t ; !!!
(every #'eq *alist-0* *alist-1*)
==> t
i.e., the cells are the same, but the lists are different.
It would probably be better to consistently copy all cells:
(defparameter *alist-2*
(mapcar (lambda (x)
(if (zerop (random 2))
(cons (cdr x) (car x))
(cons (car x) (cdr x))))
*alist-0*))
*alist-0*
==> ((B . 21) (O . 24) (P . 15) (R . 47) (K . 49))
*alist-2*
==> ((21 . B) (O . 24) (15 . P) (R . 47) (K . 49))