2016-04-27 125 views
0

我有这个功能用Lisp:Lisp的 - 排序使用自定义函数

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

我有排序使用自定义函数(这里命名pathLength)的列表。我读了lisp有关sort的文档,但我无法理解一件事。我的问题是我究竟在给我的比较功能?

比较功能:

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

回答

4

比较函数(在这种情况下是>)得到两个参数(两个元件被比较)。在比较之前,参数将通过关键函数(pathLength)。您可以使用TRACE来查看调用哪些函数。例如:

(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 

关于你的代码的一些评论。

  1. 在Lisps中,函数和变量的命名约定是使用所有小写字母之间的破折号。所以add-to-queue而不是AddtoQueue。名称(符号)通常会自动转换为大写(并且在注释等中写入),但在编写实际代码时应使用小写。
  2. 你不应该把闭幕paren放在自己的路线上。使用换行符和缩进来显示程序的结构。
  3. 应使用LET而不是SETQ来定义局部变量。
  4. 由于CONDADD-TO-QUEUE只比较METHODEQ符号,CASE会更适合该任务。
  5. 您的PATH-LENGTH正在使用变量QUEUE,它位于ADD-TO-QUEUE的本地。您需要使用FLET在同一范围内移动该功能。
  6. 它也使用名为TERMINALCOORDS的变量,这两个变量似乎都不存在于任何一个函数中。如果这些是全局(特殊)变量(应使用DEFVAR or DEFPARAMETER定义),则应在名称周围添加耳罩(星号)以表明:*TERMINAL*,*COORDS*

我不能没有完整的代码进行测试,但代码应该是这个样子:

(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

完美答案,谢谢你。你指出了更多我等待得到的东西。只用了一个月的Lisp。 – Segmentation