Question

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

Was it helpful?

Solution

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

OTHER TIPS

As I see here, you have multiple problems...

(define (playTourneyRound knightList)
  (
   ...
  )
)

You have useless parenthesis here, it means that you are going to execute the first statement returned by what is going to be evaluated between the (...). Since you are following it with a cond then (list '() '()). It doesnt make much sense...

You could have written that thought:

(define (playTourneyRound knightList)
  (begin
   ...
  )
)

But this is more than enough without anything:

(define (playTourneyRound knightList)
  ...)

Also, what I can say for now is that since none of what you do has sideeffect, it will never append anything or change any object What you may wanted to write is:

(set! winners (append ...))
(set! loosers (...))

But since you're not calling anything else, and that the last statement in you function returns a list of empty lists... The function doesn't do anything and doesn't iterate over the list of elements.

You should try something more simpler.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top