Question

Why is there an error about redefining a constant in code that doesn't redefine a constant?

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?

 3  44  3
1 Jan 1970

Solution

 4

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.

2024-07-11
Sorawee Porncharoenwase