Common lisp Lisp:psetf未完全理解
我在SBCL中尝试此操作以翻转列表中的虚线对:Common lisp Lisp:psetf未完全理解,common-lisp,Common Lisp,我在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
(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)))
但是我得到了这个(ymmv):
这告诉我psetf不喜欢我正在做的事情。据我所知,
psetf
是破坏性的,返回NIL
。我在这里不明白什么?您观察到的行为是正确的,也是预期的:
返回nil
并放置返回值
进入返回列表,因此当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))
实际上,CL有一个宏
仅针对您的情况:
(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))
最后,请注意:
i、 例如,单元格相同,但列表不同
一致复制所有单元格可能会更好:
(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))
通常,人们可能希望避免修改cons单元格<代码>缺点新的
CL-USER 76 > (mapcar (lambda (pair)
(if (= (random 2) 0)
(cons (cdr pair)
(car pair))
pair))
'((B . 21) (O . 24) (P . 15) (R . 47) (K . 49)))
((21 . B) (24 . O) (P . 15) (47 . R) (49 . K))
请注意,结果中的某些cons单元格来自引用的数据。
(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))
CL-USER 76 > (mapcar (lambda (pair)
(if (= (random 2) 0)
(cons (cdr pair)
(car pair))
pair))
'((B . 21) (O . 24) (P . 15) (R . 47) (K . 49)))
((21 . B) (24 . O) (P . 15) (47 . R) (49 . K))