The following code:
#lang racket
(define foo1234
(call/cc
(lambda (j) (j (lambda (_) (j 5))))))
(foo1234 (lambda (_) 2))
Produces an error about redefining a constant:
define-values: assignment disallowed;
cannot re-define a constant
constant: foo1234
in module:"/Users/mheiber/one.rkt"
But I'm not redefining a constant!
What is the error message trying to telling me?
But you are, through the continuation!
It might be clearer to take a look at the following program:
#lang racket
(define cont
(let ([k* (call/cc (λ (k) k))])
(println (list 'hello k*))
k*))
(println 'world)
(cont 1)
The above program results in:
'(hello #<procedure>)
'world
'(hello 1)
define-values: assignment disallowed;
cannot re-define a constant
constant: cont
in module:'anonymous-module
assuming that you have "Enforce constant definitions" ticked in the language setting of DrRacket (which is the default IIUC).
Why? When call/cc
is executed, we capture the continuation, which is:
(define cont
(let ([k* <hole>])
(println (list 'hello k*))
k*))
and binds the continuation to k*
. Then, we print the first "hello". We then bind the same continuation to cont
.
Next, we print "world".
Then, we invoke the continuation with 1
, so we are executing
(define cont
(let ([k* 1])
(println (list 'hello k*))
k*))
and this is when the second "hello" is printed. Then, we redefine cont
, which is when the error occurs.
Note that it is possible to avoid the error by unticking "Enforce constant definitions" in the language setting of DrRacket. But yes, you do redefine the variable.