2016-11-02 6 views
2

Ich versuche, um die Funktion zu verwenden orderlistofcoordinates eine Liste von Koordinaten zu sortieren wie ((3 15) (4 15) (5 15) (3 16) (4 16) (5 16))nicht Liste sortieren

Die Funktionsdefinition ist:

(defun orderlistofcoordinates (coordlist) 
    ;; order list of coordinates 
    (stable-sort (copy-alist coordlist) 
       #'(lambda (x y) 
        (> (+ (* (car x) 10) 
         (second x)) 
         (+ (* (car y) 10) 
         (second y)))))) 

Ich verstehe, was die Funktion tun, aber wie kann ich eine Variable eine Liste von Koordinaten zuweisen und dann mit der Funktion sortieren?

Ich habe eine harte Zeit in Lisp kommen, von einem C-Hintergrund kommen.

Antwort

2

SORT, STABLE-SORT haben folgende Signatur:

sequence predicate &key key => sorted-sequence 

Der Rückgabewert ist der sortierten Sequenz. Die Sortierfunktionen erlauben jedoch durch die Sprachspezifikation, die in der Eingabe angegebene Reihenfolge zu ändern, was schlimme Folgen haben kann, wenn die Originaldaten von einem anderen Teil des Codes referenziert werden (aber für temporäre Listen völlig in Ordnung). Um Ihre Sicherheit zu gewährleisten, weist Ihre Funktion zuerst eine neue Liste zu, indem Sie eine Kopie erstellen.

Im Gegensatz zu Sprachen, in denen Funktionen Verweise auf Variablen außerhalb ihres Umfangs nehmen können, können Sie keine lexikalische Bindung ändern, die aus dem Innern einer Funktion in Common Lisp nicht erreichbar ist (man kann mit dynamischer Bindung, das heißt spezielle Variablen). Um zu klären, kann eine lokale Funktion Bindings ändern wie folgt:

(let ((x 1)) (lambda() (setf x (* x 2)))) 

... aber es kann eine Bindung nicht ändern kann es nicht zu sehen, wie zum Beispiel Referenzvariablen tun in C++:

void mutate(int &y) 
{ 
    y = y * 2; 
} 

void test() 
{ 
    int y = 1; 
    mutate(y); 
    /* now y equals 2 */ 
} 

In CL lassen Sie den Aufrufer für die Verwaltung seiner eigenen Bindungen verantwortlich und lassen Funktionen einfach Werte zurückgeben. Sie können immer noch einen Makro schreiben, um diesen Schritt vor dem Benutzer zu verbergen, der eine Stelle nimmt und implizit über SETF ändert. Eine schnelle und schmutzige Makro könnte zum Beispiel sein:

(defmacro sortf (sequence &rest args) 
    `(setf ,sequence (sort ,sequence ,@args)) 

Aber ich würde nicht ein Makro für einen solchen einfachen Fall schreiben. Außerdem müsste ein robustes Makro Eingaben prüfen, Dokumentation bereitstellen und möglicherweise Fehlermeldungen signalisieren.

Hier ist ein Umschreiben Ihrer Funktion, die die Vorteile der :key Argument von sort nimmt:

(defun sort-coordinates (coordinates) 
    (stable-sort (copy-alist coordinates) 
       #'> 
       :key (lambda (point) 
         (+ (* (first point) 10) (second point))))) 

Bitte beachte, dass ich Namen geändert, verwendet Bindestriche Wörter zu trennen und schrieb first statt car.

+1

Danke, diese kleinen Unterschiede machen es mir schwer in LISP zu kommen. –

2

Das Problem kann sein, dass Sie denken, dass die Liste, die Sie übergeben, geändert wird, wenn stattdessen die Funktion eine neue Liste mit den gleichen Koordinaten, aber in sortierter Reihenfolge zurückgibt. Wenn Sie also diesen Wert einer Variablen zuweisen möchten, müssen Sie den neuen Wert abrufen, indem Sie diese Funktion aufrufen und dann das Ergebnis dieser Variablen zuweisen.

+0

Also, um explizit zu sein, weisen Sie Ihre ursprüngliche Liste einer Variablen zu: '(setf original '((3 15) (4 15) (5 15) (3 16) (4 16) (5 16))) ' dann Ihre neue Liste zum Ergebnis der Funktion zuweisen: ' (setf neue (orderlistofcoordinates original)) ' Dann' new' die sortierte Liste enthält. Sortiert von hohen zu niedrigen Werten, wie es passiert. War das absichtlich? – EvansWinner

+0

@EvansWinner: Warum fragst du mich? –

+0

Vielen Dank Scott und @EvansWinner, ich habe wirklich gedacht, dass die Liste, die ich passierte, geändert würde, anstatt einer Kopie. –