-1

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

  • 7
    Your indentation is all wrong! – leppie Mar 06 '14 at 12:48
  • 1
    Hint: `(winners ...` ; does not look kosher (missing a `let` ?) – leppie Mar 06 '14 at 12:50
  • ignore the indentation issue. @leppie, the (winners ) portion appears to be working fine and actually, that doesn't seem to be the issue. – user2904660 Mar 06 '14 at 12:51
  • 1
    the `(winners ...` thing is probably wrong since it's like calling a function named `winners`. But in your case, it is a `list`. – Loïc Faure-Lacroix Mar 06 '14 at 12:59
  • @LoïcFaure-Lacroix I want to return a list of winners, and a list of losers, It's not having any trouble with that, it's not even getting that far because it's gettin to the end of the tournament and trying to return an empty list and just fails to return an empty list. I don't understand why, but I don't normally use lisp style languages. – user2904660 Mar 06 '14 at 13:03
  • Please note that "I'm new to scheme and I don't know what's wrong" isn't a title that's likely to attract people that might know how to figure out what's wrong, and it doesn't really describe the immediate problem that you're having. "no matter what I do I get an error" is a bit more specific, but the question really ought to include a copy of the error, so that there's something specific to address here. These concerns aren't unique to Scheme or other languages in the Lisp family; describing specific problems will help greatly in getting help on any programming (or other technical) problem. – Joshua Taylor Mar 07 '14 at 03:43
  • @JoshuaTaylor If you read the full thing you'd see at the bottom the error was "call of non-procedure" Also, someone did help me, and they were able to help me understand what was going wrong. Basically it came down to the fact that I was treating my operation parenthesis weren't calling anything, and the internal function wasn't returning a function to run either. Thanks for your input. It reminded me I needed to close this request. – user2904660 Mar 08 '14 at 05:19

2 Answers2

1

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)))))))    
WorBlux
  • 1,423
  • 11
  • 20
  • 1
    There's a little book out there called the little schemer, and it's great at really groking a basic mindset that's usefull for writing scheme programs. – WorBlux Mar 06 '14 at 18:20
  • thanks, that's really helpful, but I should have mentioned I wasn't allowed to use loops. I'd also already fixed the code, I still need to close this request. Thanks though, this looks really cool. – user2904660 Mar 08 '14 at 05:22
  • 1
    A named let isn't a loop. I could have named it 'inner' or 'helper' for the same result, it's just a little bit of synactic sugar over letrec. (let name ((arg1 val1) (arg2 val2) ...) body) is the same as (letrec ((name (lambda (arg1 arg2 ...) body))) (name val1 val2...)) – WorBlux Mar 08 '14 at 21:24
0

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.

Loïc Faure-Lacroix
  • 13,220
  • 6
  • 67
  • 99
  • I'm confused, I thought to define a function you had to have opening and closing parentheses to define the function being performed? I really don't get scheme, I'm much more used to c++ style syntax. – user2904660 Mar 06 '14 at 13:17
  • @user2904660 there is a fundamental difference between C/C++ and Lisp-style languages. Look up S-expressions as that is the one and only data structure everything is built upon, both code and data. – Morten Jensen Mar 06 '14 at 13:50
  • Ah, I understand much better now. Thanks, I didn't understand that everything was a list of objects, and function calls are objects that accept specific number of inputs. I see I was basically inputing more parameters into a function than the function call was expecting. That makes a lot more sense now. Thanks a lot. – user2904660 Mar 06 '14 at 13:53
  • @user2904660 no problem dude :) Lisp-style languages are very different from C-style languages and the functional paradigm plus with homoiconicity and a great macro-system makes Scheme a very powerful language. – Morten Jensen Mar 06 '14 at 13:59