我正在编写一个需要递归分析“命令”和“程序”列表的程序(它是我们的教授为生活在迷宫中的机器人发明的某种“机器人语言”的解释器)。因为我最初的实现太慢了,所以我决定使用 call-with-current-continuation。
我知道 call/cc 是如何工作的,我已经阅读了这个和这个作为解释。
我的电话/抄送是基于这部分教程:
通常我们想使用 call-with-current-continuation 来调用一些带有参数而不是转义过程的过程。例如,我们可能有一个过程,除了转义过程之外还有两个参数,因此:
(define (foo xy escape) ... (if (= x 0) (escape 'ERROR)) ...)) 我们可以通过对过程进行柯里化来解决这个问题,使其成为一个参数的过程。
[ 前面的章节应该讨论柯里化!]
假设我们想要传递 0 和 1 作为 x 和 y 的值,并将转义过程交给 foo。而不是说
(call-with-current-continuation foo) 没有将足够的参数传递给对 foo 的调用,我们说
(call-with-current-continuation (lambda (escape) (foo 0 1 escape))) lambda 表达式创建了一个完全符合我们要求的闭包。它将使用参数 0、1 和由 call-with-current-continuation 创建的转义过程调用 foo。
但是,由于某种原因它不起作用并引发此异常:
call-with-current-continuation: contract violation
expected: (any/c . -> . any)
given: #<procedure:...mazesimulator.ss:301:34>
我希望你能帮我找出我的错误并解释它发生的原因......
这是与此问题相关的代码部分:
; main program
(define (simulate state expression-list program limit)
; read the input and set global variables
(set! current-orientation (list-ref state 2))
(set! current-coordinates (list-ref state 1))
(set! current-maze (list-ref state 0))
; call the inner function
(call-with-current-continuation (lambda (exit)
(command state expression-list program limit exit)))
; this is the output
(list list-of-executed-commands (list current-maze current-coordinates current-orientation))
)
;; main recursive function
;; analyses expression-list parameter
;; evaluates its elements
;; and calls itself on the cdr of the espression-list
(define (command state expression-list program limit exit)
(if (and (not (null? expression-list))(equal? stop-command #f))
; recursion end condition, the whole procedure will be done only
; if the list is still not empty
(if (atom? expression-list) ;if the list consists of only one command
(if (equal? stop-command #f) ;positive branch - if there were no erros before
(atomic-command state expression-list program limit exit) ;call atomic-command on this element
;when flag is set to #t
(exit))
; here comes a problem with "inner ifs"
(if (atom? (car expression-list)) ;negative branch - if the first element is "if"
(if (equal? (car expression-list) 'if) ;if the list consisits only of if-clause, no other commands ((if ...))
(if ((name->function (list-ref expression-list 1))) ;evaluate the boolean - wall? north? and choose corresponding branch
(command state (list-ref expression-list 2) program limit exit)
(command state (list-ref expression-list 3) program limit exit))
(evaluate-first-and-call-command-on-rest expression-list program limit exit))
(if (equal? (car(car expression-list)) 'if) ;if the if-clause is not the only element in list - "inner if" ((if ...) turn-left put-mark)
(begin ;not only evaluate if-clause,
(if ((name->function (list-ref (car expression-list) 1)))
(command state (list-ref (car expression-list) 2) program limit exit)
(command state (list-ref (car expression-list) 3) program limit exit))
(command state (cdr expression-list) program limit exit)) ;but also call command on cdr!
(evaluate-first-and-call-command-on-rest expression-list program limit exit))))
;when limit is exceeded or when the flag is set to #t
(exit) ))