Lisp-使用自定义函数进行排序

Lisp-使用自定义函数进行排序,lisp,common-lisp,Lisp,Common 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 me

我在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关于排序的文档,但我一点也不懂。我的问题是,我到底在向比较函数输入什么

比较功能:

(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)
)
比较函数(在本例中为
)获取两个参数(两个被比较的元素)。参数将在比较之前通过键函数(
pathLength
)。您可以使用查看调用函数的内容。例如:

(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
关于代码的一些注释

  • 在Lisps中,函数和变量的命名约定是在单词之间使用带破折号的所有小写字母。因此
    添加到队列
    而不是
    添加到队列
    。名称(符号)通常自动转换为大写(并在注释等中写入),但在编写实际代码时,应使用小写
  • 你不应该把结束语放在自己的行上。使用换行符和缩进显示程序的结构
  • 应使用而不是
    SETQ
    定义局部变量
  • 由于
    ADD-TO-QUEUE
    中的
    COND
    仅在
    方法
    EQ
    符号时才进行比较,因此更适合该任务
  • 您的
    路径长度
    正在使用变量
    队列
    ,该变量是
    添加到队列
    的本地变量。您需要使用将函数移动到同一范围内
  • 它还使用了名为
    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"))))
    
    比较函数(在本例中为
    )获取两个参数(两个被比较的元素)。参数将在比较之前通过键函数(
    pathLength
    )。您可以使用查看调用函数的内容。例如:

    (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
    
    关于代码的一些注释

  • 在Lisps中,函数和变量的命名约定是在单词之间使用带破折号的所有小写字母。因此
    添加到队列
    而不是
    添加到队列
    。名称(符号)通常自动转换为大写(并在注释等中写入),但在编写实际代码时,应使用小写
  • 你不应该把结束语放在自己的行上。使用换行符和缩进显示程序的结构
  • 应使用而不是
    SETQ
    定义局部变量
  • 由于
    ADD-TO-QUEUE
    中的
    COND
    仅在
    方法
    EQ
    符号时才进行比较,因此更适合该任务
  • 您的
    路径长度
    正在使用变量
    队列
    ,该变量是
    添加到队列
    的本地变量。您需要使用将函数移动到同一范围内
  • 它还使用了名为
    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"))))
    

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