New follow-up: So at this point I am puzzled by the poster's question. GoZoner has pointed out that the continuation passed by call/cc
may require an actual parameter when invoked, but this is not generally true in Racket (which, based on the poster's error message, is the language implementation that I assume is under discussion).
Furthermore, the code snippet that the original poster put in the question is incomplete, so one cannot directly execute the code in an attempt to replicate the problem. (My informal analysis hasn't revealed an obvious bug in the use of call-with-current-continuation
that was presented by the original poster.) It would be useful if the original poster could derive a minimal (or at least smaller) test case that exposes the same issue.
It could be that one of the specific languages or language levels within Racket uses a more restrictive form of call/cc
, but I have not found evidence of such a language level. I will pose the question to the original poster.
Edit: Chris-Jester Young has pointed out that my commentary may not apply properly here (see comments on this answer). I need to more carefully investigate the Racket's handling of continuations in imperative code; the notes below may be leading the asker down an incorrect path. (I plan to delete this answer if I can confirm that my notes below are bogus.)
Follow-up edit: It appears that Racket's handling of call/cc
does indeed pass along a continuation that will accept zero values when it is invoked from a context that discards the value. For example:
(define global 7)
(define (goner exit)
(set! global 11)
(exit)
(set! global 13)
(* 2 3))
(define (hi)
(define x global)
(call-with-current-continuation goner)
(* 5 x global))
(* 5 7 11)
(hi)
The above prints 385 (twice); once for (* 5 7 11)
, and once for (hi)
.
(Original commentary follows)
The fact that you are invoking (exit)
with zero arguments leads me to think that you do not completely understand how call/cc
works (as in its observable behavior), despite your claim to the contrary.
I recommend you play with some small examples, completely independently of your professor's robot maze infrastructure, before you try to incorporate call/cc
into your solution.
For example, I can readily reproduce your error message this way:
(define (goner)
(* 2 3))
(define (hi)
(let ((x (call-with-current-continuation goner)))
(* 5 x)))
(hi)
From the above, I get:
call-with-current-continuation: contract violation
expected: (any/c . -> . any)
given: #<procedure:goner>
which is quite similar to your error message, no? (Though to be honest, that might just be a coincidence).
Compare the output from the run above with the outputs from runs of:
(define (goner exit)
(* 2 3))
(define (hi)
(let ((x (call-with-current-continuation goner)))
(* 5 x)))
(hi)
and:
(define (goner exit)
(* 2 (exit)))
(define (hi)
(let ((x (call-with-current-continuation goner)))
(* 5 x)))
(hi)
and:
(define (goner exit)
(* 2 (exit 3)))
(define (hi)
(let ((x (call-with-current-continuation goner)))
(* 5 x)))
(hi)
and:
(define (goner exit)
(* (exit 2) 3))
(define (hi)
(let ((x (call-with-current-continuation goner)))
(* 5 x)))
(hi)
Give some careful thought to what each is illustrating, and think about how it might matter in the case of your program.