Lisp:psetf还没有完全理解

时间:2017-11-30 02:47:54

标签: common-lisp

我在SBCL中试图翻转列表中的虚线对:

attributeBindings: ['customStyle:style'],
customStyle: computed('top', 'height', {
  get() {
      let top = this.get('top');
      let height = this.get('height');
      return `top:${top}px; height:${height}px;`;
  }
})

但是我得到了这个(ymmv):

(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)))

告诉我(NIL (O . 24) NIL (R . 47) (K . 49)) 不喜欢我在做什么。据我了解,psetf具有破坏性并返回psetf。我在这里不理解什么?

2 个答案:

答案 0 :(得分:9)

您观察到的行为是正确的和预期的: psetf返回nilmapcar放置返回值 进入返回列表,所以当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有一个宏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))

最后,请注意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

即,细胞是相同的,但列表是不同的。

持续复制所有细胞可能会更好:

(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))

答案 1 :(得分:3)

通常人们可能希望避免修改缺陷细胞。 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))