I'm writing a function that takes a single list of knights that fight. The code running their fights is working(jousting-game), now I'm writing a tournament system and I can't get my tournament round to work. As I said, it takes a list of knights and has them fight recursively until everyone has fought, and returns two lists, one of winners, one of losers. I've tried everything I know and no matter what I do I get an error and the code refuses to work, and I don't understand why. Here's what I've written so far:
(define (playTourneyRound knightList)
(
(cond
((> (length knightList) 1)
(let (
(winner (jousting-game (car knightList) (cadr knightList)))
(winners (list))
(losers (list))
(results (playTourneyRound (cddr knightList)))
)
(if (= winner 1) (winners (append winners (list (car knightList)))) (winners (append winners (list (cadr knightList)))))
(winners (append (car results)))
(losers (list (cadr knightList) (cadr results)))
(list winners losers)
)
)
((= (length knightList) 1)
(list knightList)
)
)
(list '() '())
)
)
Can someone please explain to me why I'm getting the error "Call of non-procedure: #", and how can I avoid this error in future? I'm sure I just don't understand something about scheme/lisp that's important, and I could really use an explanation.
Thanks for all the help, problem has been solved
First think you should know scheme is lexically scoped. Variable declaration are only meaningful in the code frame they are declared or child frames.
Also you opened with double parenthesis, which is not usually what you want to do, unless the inner set returns a function and you want to apply it.
Your pretty printing is way off. Cond
statements should be on a single line, or lined up on the second parenthesis of the clause. If
only has three clauses, and should again be all on the same line, or on subsequent lines aligned with the first argument. The function body of a let
statement should be lined up with the "e" or "t" of let. Trailing parnethesis on their own line is generally frowned upon.
Calling length repeatedly in a recursion is bad form, as length
is a O(n) operation to the length of the list just check if the list is null or the cdr is null
And you really need and inner function to do what you're trying to do. (inner define, letrec, or named let will do)
If you're appending like (append <some-list> (list <some list element>))
you're doing it poorly. First off append
is O(n) to the length of the first argument. Just go ahead and accumulate the results in the reverse order, and reverse that at the end.
(define (playTourneyRound knightList)
(let loop ((knights-L knightList) ;;named let
(winners (list))
(losers (list)))
(cond ((null? knight-L) (map reverse (list winners losers))) ;;length = 0
((null? (cdr knight-L) ;;lenght = 1
(loop (cdr knight-L)
(cons (car knight-L) winners)
losers))
(else ;; length > 1
(let* ((winner (jousting-game (car knight-L) (cadr knight-L)))
;;assuming that jousting-game return the winning knight
(loser (if (equal? winner (car knight-L))
(cadr knight-L)
(car knight-L))))
(loop (cddr knight-L)
(cons winner winners)
(cons loser losers)))))))