我在SBCL中试图翻转列表中的虚线对:
(mapcar (lambda (x) (let ((num (random 2)))
(if (= num 0)
(psetf (cdr x) (car x) (car x) (cdr x))
x)))
'((B . 21) (O . 24) (P . 15) (R . 47) (K . 49)))
Run Code Online (Sandbox Code Playgroud)
但是我得到了这个(ymmv):
(NIL (O . 24) NIL (R . 47) (K . 49))
Run Code Online (Sandbox Code Playgroud)
这告诉我psetf不喜欢我在做什么.据我了解,psetf具有破坏性和回报NIL.我在这里不理解什么?
您观察到的行为是正确的和预期的:
psetf返回nil
并将mapcar返回值放入返回列表中,因此当num为0时,您到达那里nil,当它为1时,您将获得原始单元格.
轻松修复:
(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))
Run Code Online (Sandbox Code Playgroud)
实际上,CL rotatef
只有你的情况下有一个宏:
(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))
Run Code Online (Sandbox Code Playgroud)
最后,请注意修改引用的数据是一个非常糟糕的主意:
(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
Run Code Online (Sandbox Code Playgroud)
即,细胞是相同的,但列表是不同的.
始终复制所有单元格可能会更好:
(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))
Run Code Online (Sandbox Code Playgroud)