2016-07-15 18 views
1

Vorwort: Ich mache gerade einen komprimierten Kurs, der anscheinend in LISP gelehrt wird und ich habe nie mit LISP in meinem Leben gearbeitet, also musste ich die Sprache über eine lernen Wochenende. Ich entschuldige mich im Voraus für den abgründigen Code. Ich kenne LISP nur so gut, dass der Code funktioniert und nicht viel mehr.Common LISP (SBCL): Rückgabe von Werten innerhalb von Schleifen

Ich arbeite gerade an einem Programm, das das Problem der Karteneinfärbung löst. Dieser Code nimmt eine Sequenz an, bei der das erste Element jeder Untersequenz ein Zustand und das zweite Element eine Farbe darstellt. ex: '((A R) (B G) (C G) (D Y) (E B) (F B)) und überprüft dann, ob kein Zustand die gleiche Farbe hat wie ein durch ihn eingeschränkter Zustand (definiert durch die Beschränkungsliste). Ich weiß, dass es wahrscheinlich viel sauberere und einfachere Wege gibt, dies zu tun, aber was ich momentan damit zu tun habe, ist, dass meine Dolist-Schleifen sofort den Wert T zurückgeben, wenn die if-Anweisung erfüllt wird. Bisher konnte ich die Funktionen nicht einfach einen Wert zurückgeben und musste auf diese wirklich hässliche/falsche Methode zurückgreifen, um eine Variable auf "true" zu setzen und darauf zu warten, dass die Schleife beendet wird, damit der Code funktioniert. Ich habe versucht, Return und nur T innerhalb der if-Anweisungen verwenden, aber in beiden Fällen würde die Schleife beenden statt einen Wert zurückgeben und ich habe keine Ahnung warum.

(setq constraint '((A (B C E)) (B (A E F)) (C (A E F)) (D (F)) (E (A B C F)) (F (B C D E)))) 

(defun check_constraint (f s) 
    (setf ans nil) 
    (dolist (state constraint) 
     (if (eq (first state) f) 
      (if (search (list s) (second state)) 
       (setf ans T) ;;where I want it to just return T 
      ) 
     ) 
    ) 
    ans 
) 

;;ex: ((A R) (B R) (C B) (D R) (E B) (F G)) 
(defun check_conflict (lst) 
    (setf anb nil) 
    (dolist (state lst) 
     (dolist (neighbor (remove state lst)) 
      (if (check_constraint (first state) (first neighbor)) 
       (if (eq (second state) (second neighbor)) 
        (setf anb T)) ;;where I want it to just return T 
      ) 
     ) 
    ) 
    anb 
) 

EDIT: Ich endete nur dies mit Rekursion zu beheben. Der Code ist jetzt sauberer, aber ich würde immer noch gerne wissen, was mein Problem ist. Dies ist der rekursive Code.

(setq constraint '((A (B C E)) (B (A E F)) (C (A E F)) (D (F)) (E (A B C F)) (F (B C D E)))) 

(defun check_constraint (lst f s) 
    (COND 
     ((null lst) nil) 
     ((search (list (car (car lst))) f) 
      (if (search s (second (car lst))) T)) 
     (t (check_constraint (cdr lst) f s)) 
    ) 
) 

(defun check_neighbor (check lst) 
    (COND 
     ((null lst) nil) 
     ((check_constraint constraint (list (car check)) (list (first (first lst)))) 
      (if (eq (second check) (second (car lst))) T)) 
     (t (check_neighbor check (cdr lst))) 
    ) 
) 

;;(check_state '((A R) (B R) (C B) (D R) (E B) (F G))) 
(defun check_state (lst) 
    (COND 
     ((null lst) nil) 
     ((check_neighbor (car lst) (cdr lst)) T) 
     (t (check_state (cdr lst))) 
    ) 
) 
+0

Es gibt viele lisp Dialekte, und Sie sagen nicht, welche. In den meisten Dialekten gibt es eine spezielle Form 'return', die verwendet werden kann, um einen Wert von einer höheren Form zurückzugeben.Leider, welche Formen es betrifft, ist eines der Dinge, die sich zwischen Dialekten unterscheiden. Also mit '(return T)' an diesem Punkt würde arbeitet die meisten der Dialekte ich weiß, [und Sie tun können, weg mit dem Vars 'ans' und' anb' und nur noch 'NIL' nach der Schleife]. – MAP

+0

@MAP Es ist allgemeines Lispeln und wenn ich das versuche, konnte ich es nicht in SBCL arbeiten lassen. – Metasyntactic

Antwort

4

Zuerst ein paar Stilprobleme. Sie sollten DEFVAR or DEFPARAMETER verwenden, um globale Variablen zu deklarieren. Diese sollten auch Sternchen um den Namen haben, um zu zeigen, dass sie global sind (oder speziell).

(defparameter *constraint* 
    '((A (B C E)) 
    (B (A E F)) 
    (C (A E F)) 
    (D (F)) 
    (E (A B C F)) 
    (F (B C D E)))) 

Die Lisp-Konvention für die Dinge zu benennen ist Bindestriche zwischen Wörtern (CHECK-CONSTRAINT statt CHECK_CONSTRAINT) zu verwenden. Sie sollten auch vollständige Wörter für Variablennamen anstelle von Abkürzungen bevorzugen (LIST statt LST). Die abschließenden Klammern sollten nicht in einer eigenen Zeile stehen.

Dann das eigentliche Problem. Sie können RETURN verwenden, um einen Wert aus einem Block namens NIL zurückzugeben. Loops schaffen einen solchen Block, so dass Sie die erste Funktion wie

(defun check-constraint (first second) 
    (dolist (state *constraint*) 
    (when (and (eq first (first state)) 
       (member second (second state))) 
     (return t)))) 

Es ist besser schreiben WHEN statt IF zu verwenden, wenn es nur ein then-Zweig. Ich habe auch die zwei IF s in eins unter Verwendung AND kombiniert. Da Sie S in eine Liste für die Verwendung von SEARCH gewickelt haben, dachte ich, dass Sie wahrscheinlich stattdessen MEMBER verwenden möchten (obwohl ich nicht sicher bin, da ich nicht genau weiß, was der Code tun soll). Sie können das ändern, wenn es falsch ist.

Sie könnten wahrscheinlich vereinfachen es auch

(defun check-constraint (first second) 
    (member second (second (find first *constraint* :key #'first)))) 

In der zweiten Funktion können Sie zwei Schleifen haben. Wenn Sie RETURN verwenden, um von der inneren zurückzukommen, beenden Sie einfach die äußere Schleife und ignorieren den Rückgabewert. Sie müssen also RETURN-FROM verwenden, um von der Funktion anstelle der inneren Schleife zurückzukehren.

(defun check-conflict (list) 
    (dolist (state list) 
    (dolist (neighbor (remove state list)) 
     (when (and (check-constraint (first state) (first neighbor)) 
       (eq (second state) (second neighbor))) 
     (return-from check-conflict t))))) 
+0

Das ist perfekt! Danke, dass Sie sich die Zeit genommen haben, mich auch durch einige Stilfragen zu führen. Ich habe mich beeilt, das so schnell wie möglich aufzuheben und die Kursressourcen sind ein wenig begrenzt. Das war sehr informativ. – Metasyntactic