2017-11-30 11 views
3
私はリスト内の点線のペアを反転するSBCLでこれをしようとしている

:私は(メーリングリスト)これを取得しかしは、Lisp:psetfは完全には理解されていない

(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は破壊的で、NILを返します。私はここで何を理解していないのですか?

答えて

9

あなたが観察行動は正しいと期待されている:numが0であるとき psetf戻っnilmapcar場所リターンリストに戻り値 は、そう、あなたがそこに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 があります、

(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 

すなわち:

(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に注意してくださいセルは同じですが、リストは異なっていますnt。

おそらく一貫してすべてのセルをコピーする方が良いでしょう:

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

多くの場合、1つはコンスセルを変更しないようにしたいかもしれません。 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)) 
+0

結果の一部のコンスセルは、引用されたデータに由来することに注意してください。 – sds

関連する問題