0
votes

I am currently using racket scheme with DrRacket as the editor for some exploratory programming. When I try and redefine a function I get the following message:

define-values: cannot re-define a constant: png->byte-list

Now I used to accept that this was a property of the language and was frustrated by it but kind of accepted it. Having read How can you re-define a constant identifier in DrScheme? I can see that I don't necessarily have to accept this limitation.

My questions are as follows:

  1. Is this feature only available in the R5RS language? Is there a way to switch this feature off for an arbitrary language?
  2. Alternatively if I switch the R5RS language will this have an impact on me using the modules I'm using at the moment: racket/gui/base and web-server/insta?
3

3 Answers

4
votes

Such re-definitions are possible with #lang racket if you do them in the definitions window. The thing to keep in mind is that this is not a kind of mutation (which is common with R5RS implementations), for example, this:

#lang racket
(define orig-+ +)
(define + whatever)

will not have orig-+ bound to the real addition function. When this module is compiled, Racket knows (statically) that + is something that you define, so any references to it are references to your own definition -- so the above code will bind orig-+ to the "uninitialized" value of +. If you really want to do something like that, then you can require the original + under a different name:

#lang racket
(require (rename-in racket [+ orig-+]))
(define + whatever)

On top of that, there's inlining that happens when the module is compiled -- which is a different issue. Racket will usually want to inline references to bindings that are never mutated in the code, so if you try that last piece of code you will not be able to further redefine + on the REPL. You can deal with that in one of two ways -- the first is to mutate the binding explicitly:

#lang racket
(require (rename-in racket [+ orig-+]))
(define + #f)
(set! + whatever)

which makes the compiler avoid any inlining. Another option is that DrRacket flag, which turns on a compiler flag that avoids all inlining. Note that the speed penalty for this can be significant.

0
votes

1 - I'm no pro in Scheme, but I just tried to redefine multiplication function (* ). It doesn't work with "Disallow redefinition of initial bindings". But if unchecked - it works:

Welcome to DrRacket, version 5.0.2 [3m].
Language: R5RS [custom]; memory limit: 128 MB.
> (* 2 2)
4
> (define (* a b) a)
> (* 2 2)
2
>

However, I was not able to get your error (define-values: cannot re-define a constant:...) If i redefine existing function i get (define-values: cannot change constant variable:...)

2 - I would think that if modules have #lang directive that specifies explicitly the language it should not be a problem (I guess).

0
votes

Here is how to define multiplication

(define multiply *) ; variable named "multiply" with a value of *