我是计划的新手,我不知道出了什么问题

时间:2014-03-06 12:46:09

标签: scheme chicken-scheme

我正在编写一个功能,只需要一个战斗骑士列表。运行他们的战斗的代码是工作(角逐游戏),现在我正在写一个锦标赛系统,我不能让我的锦标赛轮次上班。正如我所说,它需要一个骑士名单并让他们以递归方式进行战斗,直到每个人都进行了战斗,然后返回两个名单,其中一个是赢家,一个是输家。我已经尝试了我所知道的一切,无论我做什么,我都会收到错误而且代码拒绝工作,我不明白为什么。这是我到目前为止所写的内容:

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

有人可以向我解释为什么我收到错误“非程序调用:#”,以后如何避免此错误?我确定我只是不了解有关scheme / lisp的重要内容,我真的可以使用解释。

感谢所有帮助,问题已经解决

2 个答案:

答案 0 :(得分:1)

首先想你应该知道方案是词法范围的。变量声明仅在声明它们的代码帧或子帧中有意义。

你也打开了双括号,这通常不是你想要做的,除非内部集合返回一个函数而你想要应用它。

你漂亮的印刷很遥远。 Cond语句应该在一行上,或者在子句的第二个括号上排成一行。 If只有三个子句,并且应该全部在同一行上,或者在与第一个参数对齐的后续行上。 let语句的函数体应与let的“e”或“t”对齐。在他们自己的路线上追踪parnethesis一般不赞成。

在递归中重复调用长度是不好的形式,因为length是对列表长度的O(n)操作,只检查列表是否为空或cdr是否为空

你真的需要和内在的功能去做你想做的事情。 (内部定义,letrec或​​命名let将执行)

如果你像(append <some-list> (list <some list element>))一样追加,那么你做得很差。首先关闭append是O(n)到第一个参数的长度。然后继续以相反的顺序累积结果,并在结束时反转结果。

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

答案 1 :(得分:0)

正如我在这里看到的,你有很多问题......

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

这里有无用的括号,这意味着你将执行(...)之间要评估的内容返回的第一个语句。由于您使用cond然后(list '() '())关注它。它没有多大意义......

你本可以写下这个想法:

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

但是没有任何东西就足够了:

(define (playTourneyRound knightList)
  ...)

此外,我现在可以说的是,由于你所做的一切都没有副作用,它永远不会附加任何东西或改变任何对象你可能想写的是:

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

但是因为你没有调用任何其他东西,并且你函数中的最后一个语句返回一个空列表列表......该函数没有做任何事情,也没有遍历元素列表。

你应该尝试更简单的事情。