2016-04-27 12 views
0

Ich habe diese Funktion in Lisp:Lisp - Sortierung mit benutzerdefinierter Funktion

(defun AddtoQueue (queue method) 
    (cond 
    ((eq method 'DFS) (append (growPath (car queue) (findCh (caar queue))) (cdr queue))) 
    ((eq method 'BFS) (append (cdr queue) (growPath (car queue)(findCh (caar queue))))) 
    ((eq method 'A) (SORT (append (cdr queue) (growPath (car queue) (findCh (caar queue)))) #'> :key #'pathLength )) 
    (T "not implemented") 
) 
) 

Ich habe eine Liste zu sortieren, eine benutzerdefinierte Funktion (hier pathLength genannt). Ich lese Lisp Dokumentation über sort, aber ich kann nichts verstehen. Meine Frage ist was genau füttere ich meine Vergleichsfunktion?

Vergleichsfunktion:

(defun pathLength(point) 

    ;;distance from origin point 
    (setq x (- (length queue) 1)) 

    ;;distance from end(manhattan distance) by subtracting the coords. 
    ;;calc lists is adding or subtracting lists. 
    (setq y (calcLists (cadr (assoc (car point) coords)) (cadr (assoc terminal coords)) 'sub)) 


    (setq y (+ (car y) (cadr y))) 
    ;;sum of distance from start and end. 
    (+ x y) 
) 

Antwort

4

Die Vergleichsfunktion (die in diesem Fall ist >) erhält zwei Argumente (zwei Elemente verglichen werden). Die Argumente durchlaufen vor dem Vergleich die Schlüsselfunktion (pathLength). Sie können TRACE verwenden, um zu sehen, wie die Funktionen aufgerufen werden. Zum Beispiel:

(trace >) 
;=> (>) 
(sort (list 4 5 1) #'>) 
; 0: (> 5 4) 
; 0: > returned T 
; 0: (> 1 4) 
; 0: > returned NIL 
;=> (5 4 1) 
(trace 1+) 
;=> (1+) 
(sort (list 4 5 1) #'> :key #'1+) 
; 0: (1+ 5) 
; 0: 1+ returned 6 
; 0: (1+ 4) 
; 0: 1+ returned 5 
; 0: (> 6 5) 
; 0: > returned T 
; 0: (1+ 1) 
; 0: 1+ returned 2 
; 0: (1+ 4) 
; 0: 1+ returned 5 
; 0: (> 2 5) 
; 0: > returned NIL 
;=> (5 4 1) 
(untrace > 1+) 
;=> T 

Ein paar Kommentare zu Ihrem Code.

  1. In Lisps besteht die Namenskonvention für Funktionen und Variablen darin, alle Kleinbuchstaben mit Bindestrichen zwischen Wörtern zu verwenden. So add-to-queue anstelle von AddtoQueue. Die Namen (Symbole) werden normalerweise automatisch in Großbuchstaben umgewandelt (und so in Kommentare und solche geschrieben), aber beim Schreiben des tatsächlichen Codes sollten Sie Kleinbuchstaben verwenden.
  2. Sie sollten den schließenden paren nicht in eine eigene Zeile setzen. Verwenden Sie Zeilenumbrüche und Einrückungen, um die Struktur des Programms anzuzeigen.
  3. Lokale Variablen sollten unter Verwendung von LET anstelle von SETQ definiert werden.
  4. Da die COND in ADD-TO-QUEUE vergleicht nur, wenn METHODEQ auf ein Symbol ist, CASE besser für die Aufgabe geeignet wäre.
  5. Ihr PATH-LENGTH verwendet die Variable QUEUE, die lokal zu ADD-TO-QUEUE ist. Sie müssen die Funktion innerhalb desselben Bereichs verschieben, indem Sie FLET verwenden.
  6. Es verwendet auch Variablen namens TERMINAL und COORDS, die in keiner der Funktionen zu existieren scheinen. Wenn es sich um globale (spezielle) Variablen handelt (die mit DEFVAR or DEFPARAMETER definiert werden sollten), sollten Sie um die Namen Ohrenschützer (Sternchen) hinzufügen, um Folgendes anzuzeigen: *TERMINAL*, *COORDS*.

Das kann ich nicht testen, ohne den vollständigen Code, aber der Code soll wie folgt aussehen:

(defun add-to-queue (queue method) 
    (flet ((path-length (point) 
      (let* ((x (1- (length queue))) 
        ;; It's better to use FIRST and SECOND instead of CAR and 
        ;; CADR when dealing with lists. 
        (temp (calc-lists (second (assoc (car point) *coords*)) 
            (second (assoc *terminal* *coords*)) 
            'sub)) 
        (y (+ (first temp) (second temp)))) 
      (+ x y)))) 
    (case method 
     (DFS 
     ;; Consider using full words for function names. So 
     ;; FIND-CHARACTER, assuming that's what CH means. 
     (append (grow-path (car queue) 
          (find-ch (caar queue))) 
       (cdr queue))) 
     (BFS 
     (append (cdr queue) 
       (grow-path (car queue) 
          (find-ch (caar queue))))) 
     (A 
     (sort (append (cdr queue) 
        (grow-path (car queue) 
           (find-ch (caar queue)))) 
      #'> :key #'path-length)) 
     ;; You could use `ECASE` to automatically signal an error 
     ;; if METHOD doesn't match any of the cases. 
     (otherwise "not implemented")))) 
+0

perfekte Antwort, danken Sie. Du hast mehr Dinge gezeigt, auf die ich gewartet habe. Benutze Lisp erst seit einem Monat. – Segmentation

Verwandte Themen