Reputation: 401
I have this function in 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")
)
)
I have to sort a list using a custom function (here named pathLength
) . I read lisp's documentation about sort
but i can't understand a thing. My question is what exactly am i feeding my comparison function?
Comparison function:
(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)
)
Upvotes: 1
Views: 892
Reputation: 8411
The comparison function (which in this case is >
) gets two arguments (two elements being compared). The arguments will go through the key function (pathLength
) before being compared. You can use TRACE
to see what the functions are called with. For example:
(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
A few comments about your code.
add-to-queue
instead of AddtoQueue
. The names (symbols) are usually automatically converted to upper-case (and written so in comments and such), but when writing actual code you should use lower-case.LET
instead of SETQ
.COND
in ADD-TO-QUEUE
is only comparing if METHOD
is EQ
to a symbol, CASE
would be better suited for the task.PATH-LENGTH
is using the variable QUEUE
, which is local to ADD-TO-QUEUE
. You need to move the function inside the same scope by using FLET
.TERMINAL
and COORDS
, which don't seem to exist in either of the functions. If those are global (special) variables (which should be defined using DEFVAR
or DEFPARAMETER
), you should add earmuffs (asterisks) around the names to show that: *TERMINAL*
, *COORDS*
.I can't test this without the full code, but the code should look something like this:
(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"))))
Upvotes: 5