2017-11-30 22 views
3

ich dies in SBCL bin versucht, die punktierten Paare in der Liste zu blättern:Lisp: psetf nicht vollständig verstanden

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

Jedoch habe ich diese bekommen (ymmv):

(NIL (O . 24) NIL (R . 47) (K . 49)) 

, die sagt mir, psetf gefällt mir nicht, was ich mache. Wie ich verstehe, ist psetf destruktiv und gibt NIL zurück. Was verstehe ich hier nicht?

Antwort

9

Das Verhalten Sie beobachten, ist richtig und erwartet: psetf kehrt nil und mapcar Orte der Rückgabewert in der Rückgabeliste, so dass, wenn num 0, Sie dort nil bekommen, und wenn es 1 ist, erhalten Sie die ursprüngliche Zelle.

leicht behoben:

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

tatsächlich, CL hat für Ihren Fall ein Makro rotatef gerade:

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

Schließlich Bitte beachten Sie, dass 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 

dh Die Zellen sind gleich, aber die Listen sind unterschiedlich nt.

Es wäre wahrscheinlich besser, konsequent alle Zellen kopieren:

(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

Oft die Nachteile Zellen modifizieren zu vermeiden, könnte man möchte. cons neue.

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

Beachten Sie, dass einige Cons-Zellen in Ihrem Ergebnis aus den zitierten Daten stammen. – sds

Verwandte Themen