2016-07-27 16 views
-2

Ich verstehe nicht, warum mein Programm so verhält, wie es tut.LIST Rückkehr im geschachtelten cond

(defvar A '((X Y Z) (J L O P) (G W U)) 

(defvar Z '(X W D U G)) 

(defvar STOP 'G) 

(defun ADD_to_Z(A2) 
    (prog() 
    (cond 
     ((equal (Member_Of_Z (list A2)) 0)) 
     (t (setq Z (append Z (list A2)))) 
    ) 
) 
) 

(defun Member_of_Z(cdr_A1) 

(prog(n temp) 
    (setq n 0) 
    (setq temp cdr_A1) 
    repeat 
    (cond 
    ((null temp) (return n)) 
    ((null (member (car temp) Z)) (setq n (+ n 1)) (setq temp (cdr temp))) 
    (t (setq n (+ n 0)) (setq temp (cdr temp))) 
    ) 
    (go repeat) 
) 
) 



(defun TEST(A) 

(prog(A1 A2) 

     (cond 
      ((null A) (return 'Fail)) 
      (t (setq A1 (car A)) (setq A (cdr A)) (setq A2 (car A1)) 
      (cond 
       ((equal (Member_Of_Z (cdr A1)) 0) 
       (cond 
       ((equal A2 STOP) (return 'SUCCESS)) 
       (t (ADD_to_Z A2) (setq A (cdr A)) (TEST A)) 
       ) 
      ) 
       (t (TEST A) ) 
      ) 
     ) 
    ) 

    ) 
    ) 

Tor der Funktionen: - Member_of_Z werden überprüfen, ob alle Elemente von cdr A1 bis Z. gehören Wenn sie es tun, wird es 0 zurück (eine andere Zahl sonst auf andere Weise). Dies ist, was nicht passiert war es nehme SUCCESS zurück, wenn A gleich ((G W U)) ist

  • ADD_to_Z wird A2 bis Z hinzufügen, wenn Member_Of_Z nicht 0

Problem zurückkehrt: Nicht nur A scheint nie geändert (am Ende der Funktion TEST, A ist immer noch gleich auf den ursprünglichen Wert eingestellt werden durch defvar obwohl ich es mit (setq A (cdr A)) bin zu ändern. auch ERFOLG nie zurückgegeben.

Kannst du mir helfen?

+2

Ändern Literale nicht definiertes Verhalten (oder Implementierung definiert, nie remeber) in CL. Wenn Sie eine Liste ändern möchten, verwenden Sie (list ... elements), um sie anstelle von quote zu definieren. – PuercoPop

+2

@PuercoPop Es scheint nicht zu sein, die Literaldaten zu ändern, es werden nur neue Werte zu 'A' zugewiesen (oder es wird versucht, aber der Funktionsparameter schattiert die Bindung). – jkiiski

+3

Es gibt viele logische Fehler und der Stil ist mehr wie Fortran als CL, das Beispiel ist nicht ausführbar, da Sie Funktionen weggelassen haben und da Sie keine Beispielverwendung mit erwartetem Ergebnis angegeben haben, habe ich keine Ahnung, was das ist soll tun. 'defvar'-Variablen haben keine '* oufuffs *', so dass sie nicht mit lexikalischen Variablen unterschieden werden können. Wenn Sie 'setq'-ing' A' sind, ist es der Parameter in 'test' und nicht der falsch benannte global, den Sie ändern. – Sylwester

Antwort

5

Schritt 1: Verwenden Sie die Standardformatierung (Reparieren der ersten Toplevel-Form).

(defvar A '((X Y Z) (J L O P) (G W U))) 

(defvar Z '(X W D U G)) 

(defvar STOP 'G) 

(defun ADD_to_Z (A2) 
    (prog() 
    (cond ((equal (Member_Of_Z (list A2)) 0)) 
      (t (setq Z (append Z (list A2))))))) 

(defun Member_of_Z (cdr_A1) 
    (prog (n temp) 
    (setq n 0) 
    (setq temp cdr_A1) 
    repeat 
    (cond ((null temp) (return n)) 
      ((null (member (car temp) Z)) (setq n (+ n 1)) (setq temp (cdr temp))) 
      (t (setq n (+ n 0)) (setq temp (cdr temp)))) 
    (go repeat))) 

(defun TEST (A) 
    (prog (A1 A2) 
    (cond ((null A) (return 'Fail)) 
      (t (setq A1 (car A)) 
      (setq A (cdr A)) 
      (setq A2 (car A1)) 
      (cond ((equal (Member_Of_Z (cdr A1)) 0) 
        (cond ((equal A2 STOP) (return 'SUCCESS)) 
          (t (ADD_to_Z A2) (setq A (cdr A)) (TEST A)))) 
        (t (TEST A))))))) 

Schritt 2: Verwenden Sie die Standardbenennung.

(defvar *a* '((x y z) (j l o p) (g w u))) 

(defvar *z* '(x w d u g)) 

(defvar *stop* 'g) 

(defun add-to-z (a2) 
    (prog() 
    (cond ((equal (member-of-z (list a2)) 0)) 
      (t (setq *z* (append *z* (list a2))))))) 

(defun member-of-z (cdr-a1) 
    (prog (n temp) 
    (setq n 0) 
    (setq temp cdr-a1) 
    repeat 
    (cond ((null temp) (return n)) 
      ((null (member (car temp) *z*)) (setq n (+ n 1)) (setq temp (cdr temp))) 
      (t (setq n (+ n 0)) (setq temp (cdr temp)))) 
    (go repeat))) 

(defun test (a) 
    (prog (a1 a2) 
    (cond ((null a) (return 'fail)) 
      (t (setq a1 (car a)) 
      (setq a (cdr a)) 
      (setq a2 (car a1)) 
      (cond ((equal (member-of-z (cdr a1)) 0) 
        (cond ((equal a2 *stop*) (return 'success)) 
          (t (add-to-z a2) (setq a (cdr a)) (test a)))) 
        (t (test a))))))) 

Schritt 3: PROG loswerden.

(defvar *a* '((x y z) (j l o p) (g w u))) 

(defvar *z* '(x w d u g)) 

(defvar *stop* 'g) 

(defun add-to-z (a2) 
    (cond ((equal (member-of-z (list a2)) 0)) 
     (t (setq *z* (append *z* (list a2)))))) 

(defun member-of-z (cdr-a1) 
    (let ((n 0) 
     (temp cdr-a1)) 
    repeat 
    (cond ((null temp) (return n)) 
      ((null (member (car temp) z)) (setq n (+ n 1)) (setq temp (cdr temp))) 
      (t (setq n (+ n 0)) (setq temp (cdr temp)))) 
    (go repeat))) 

(defun test (a) 
    (cond ((null a) (return 'fail)) 
     (t (let ((a1 (car a)) 
       (a (cdr a)) 
       (a2 (car a1))) 
      (cond ((equal (member-of-z (cdr a1)) 0) 
        (cond ((equal a2 *stop*) (return 'success)) 
          (t (add-to-z a2) (setq a (cdr a)) (test a)))) 
        (t (test a))))))) 

Schritt 4: Ersetzen Sie die handgerollte Schleife durch eine strukturierte Schleife.

(defvar *a* '((x y z) (j l o p) (g w u))) 

(defvar *z* '(x w d u g)) 

(defvar *stop* 'g) 

(defun add-to-z (a2) 
    (cond ((equal (member-of-z (list a2)) 0)) 
     (t (setq *z* (append *z* (list a2)))))) 

(defun member-of-z (cdr-a1) 
    (let ((n 0) 
     (temp cdr-a1)) 
    (loop :for element :in temp 
      :unless (member element *z*) 
      :do (incf n)) 
    n)) 

(defun test (a) 
    (cond ((null a) (return 'fail)) 
     (t (let ((a1 (car a)) 
       (a (cdr a)) 
       (a2 (car a1))) 
      (cond ((equal (member-of-z (cdr a1)) 0) 
        (cond ((equal a2 *stop*) (return 'success)) 
          (t (add-to-z a2) (setq a (cdr a)) (test a)))) 
        (t (test a))))))) 

Schritt 5: Ersetzen Sie zwei Klauseln COND durch IF. Reduce RETURN Formen, wenn sie in Tail-Position sowieso sind (und sie funktionieren nicht so).

(defvar *a* '((x y z) (j l o p) (g w u))) 

(defvar *z* '(x w d u g)) 

(defvar *stop* 'g) 

(defun add-to-z (a2) 
    (if (equal (member-of-z (list a2)) 0) 
     nil 
     (setq *z* (append *z* (list a2))))) 

(defun member-of-z (cdr-a1) 
    (let ((n 0) 
     (temp cdr-a1)) 
    (loop :for element :in temp 
      :unless (member element *z*) 
      :do (incf n)) 
    n)) 

(defun test (a) 
    (if (null a) 
     'fail 
     (let ((a1 (car a)) 
      (a (cdr a)) 
      (a2 (car a1))) 
     (if (equal (member-of-z (cdr a1)) 0) 
      (if (equal a2 *stop*) 
       'success 
       (progn (add-to-z a2) (setq a (cdr a)) (test a))) 
      (test a))))) 

Schritt 6: Ersetzen Sie die Schleife durch eine einfache Zählfunktion.

(defvar *a* '((x y z) (j l o p) (g w u))) 

(defvar *z* '(x w d u g)) 

(defvar *stop* 'g) 

(defun add-to-z (a2) 
    (if (equal (member-of-z (list a2)) 0) 
     nil 
     (setq *z* (append *z* (list a2))))) 

(defun member-of-z (cdr-a1) 
    (count-if-not (lambda (element) 
        (member element *z*)) 
       cdr-a1)) 

(defun test (a) 
    (if (null a) 
     'fail 
     (let ((a1 (car a)) 
      (a (cdr a)) 
      (a2 (car a1))) 
     (if (equal (member-of-z (cdr a1)) 0) 
      (if (equal a2 *stop*) 
       'success 
       (progn 
        (add-to-z a2) 
        (setq a (cdr a)) 
        (test a))) 
      (test a))))) 

An diesem Punkt habe ich immer noch keine Ahnung, was Sie versuchen zu tun. Vielleicht möchten Sie eine Liste in *a* zu finden, die vollständig in *z* enthalten ist:

(defun test (a) 
    (find-if (lambda (list) 
      (every (lambda (element) 
         (member element *z*)) 
        list)) 
      a)) 
+1

Sie könnten 'SUBSETP' in diesem letzten Ausschnitt verwenden. Vielleicht wäre 'MEMBER-IF' auch besser, da der Code einen" Booleschen "(SUCCESS/FAIL) zurückgibt. – jkiiski

+0

Ja, es gibt eine fehlende Funktion in meinem Beispiel, die 'TEST' bei einem Bedingungsfehler aufrufen soll. Die Funktion prüft, ob 'stop' in' z' steht, andernfalls wird 'test' gestartet. "test" soll alles tun, bis es eine Unterliste in "a" findet, deren Elemente alle in "z" sind und das erste Element (das ist sein "Auto") ist gleich "Stop". Wenn dies erfüllt ist, wird "Erfolg" zurückgegeben. Meine Frage ist: Können die Sterne '* ... * sicherstellen, dass das Globale aufgerufen und überriten wird? Wenn ich bei Schritt 2 aufgehört habe, wird der Code immer noch funktionieren (dh werde ich nur die richtige Syntax vermissen?) –

+0

@jkiiski siehe meinen Kommentar rechts oben –