Cannot modify a constant

hello,
i find a little bug in one of my code.
It is not easy to debug because it use a personal reader/parser,and a modified REPL for Racket . (based on this very interesting book: https://beautifulracket.com/)

i have a reader/parser that parse this infix code:

#lang reader "../src/SRFI-105.rkt"
(require "../Scheme+.rkt")

{t-init <+ 35267}

note: <+ can be seen as 'define'

that generates a Racket prefix syntax module:

Welcome to DrRacket, version 8.11 [cs].
Language: reader "../src/SRFI-105.rkt", with debugging; memory limit: 8192 MB.
SRFI-105 Curly Infix parser with optimization by Damien MATTEI
(based on code from David A. Wheeler and Alan Manuel K. Gloria.)

Options :

Infix optimizer is ON.
Infix optimizer on sliced containers is ON.

Parsed curly infix code result = 

(module aschemeplusprogram racket 
(require "../Scheme+.rkt")

(<+ t-init 35267)

)

note that the parser/reader create a scheme module this way,in summary:

(define (literal-read-syntax src in)
  
  (define lst-code (process-input-code-tail-rec in))

  ;;`(module aschemeplusprogram racket ,@lst-code))

  (strip-context `(module aschemeplusprogram racket ,@lst-code))) ;; is strip-context useful?

and at the REPL:

> t-init
35267

t-init has been defined with 'define'

i can use it but not modify it:

> (+ t-init 3)
35270

and now i got this error:

> (set! t-init 1234)
t-init: cannot modify a constant

what do the REPL, it evaluates this:

;; the current read interaction handler, which is procedure that takes an arbitrary value and an input port 
(define (literal-read-syntax-for-repl src in)

  (define result (curly-infix-read in))
  
  (if (eof-object? result)
      ;;(begin (display "eof") (newline) result)
      result
      (datum->syntax #f result))) ;; current-eval wait for a syntax object to pass to eval-syntax for evaluation
      

i suppose the problem is in the (datum->syntax #f result) or something else?
but i have no idea.

this a minor problem ,all the code works in many hundred lines programs , it is my Scheme+ REPL for Racket (Scheme-PLUS-for-Racket/src/SRFI-105.rkt at main · damien-mattei/Scheme-PLUS-for-Racket · GitHub) that have this bug. In Kawa (no REPL because no SRFI105) or Guile (partial REPL as SRFI105 exist for Guile) it works:

GNU Guile 3.0.8.99-f3ea8
Copyright (C) 1995-2022 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> (load "SssDyna.scm")
scheme@(guile-user)> t-init
$1 = 35267
scheme@(guile-user)> {t-init <- 7}
scheme@(guile-user)> t-init
$2 = 7

Regards,

Damien

A variable exported from a Racket module cannot be modified via set! in importing modules. I recommend defining and providing a modification function:

(provide 
  #; {Any -> Void} 
  change-t-init!)

(define (change-t-init! new-valie)
  (set! t-init new-value))
1 Like

yes

a simple example show that:

#lang racket
(define x 1)

Welcome to DrRacket, version 8.11 [cs].
Language: racket, with debugging; memory limit: 8192 MB.
> x
1
> (set! x 4)
. . x: cannot modify a constant

unfortunately every program in racket start by
#lang racket

which create a module as:
(module aracketprogram racket
;; the code here
)

even with 'load' in repl the program will be encapsulate in a module
and the only solution seems to remove the #lang racket

then if i parse my code in command line:

/Applications/Racket\ v8.11/bin/racket ../src/curly-infix2prefix4racket.rkt  SssRec+.rkt > ./SssRec.rkt
SRFI-105 Curly Infix parser with operator precedence by Damien MATTEI
(based on code from David A. Wheeler and Alan Manuel K. Gloria.)

Options :



Parsed curly infix code result = 

(module aschemeplusprogram racket 
(require "../Scheme+.rkt")

(<+ L-init (quote (1 3 4 16 17 24 45 64 197 256 275 323 540 723 889 915 1040 1041 1093 1099 1111 1284 1344 1520 2027 2500 2734 3000 3267 3610 4285 5027)))

(<+ t-init 35267)

(<+ cpt 0)

(define (ssigma L t) (<- cpt (+ cpt 1)) (if (null? L) (begin #f) ($+> (<+ c (first L)) (<+ R (rest L)) (cond ((= c t) #t) ((> c t) (ssigma R t)) (else (or (ssigma R (- t c)) (ssigma R t)))))))

)

i will still get the module:

cat SssRec.rkt 
(module aschemeplusprogram racket
  (require "../Scheme+.rkt")
  (<+
   L-init
   '(1
     3
     4
     16
     17
     24
     45
     64
     197
     256
     275
     323
     540
     723
     889
     915
     1040
     1041
     1093
     1099
     1111
     1284
     1344
     1520
     2027
     2500
     2734
     3000
     3267
     3610
     4285
     5027))
  (<+ t-init 35267)
  (<+ cpt 0)
  (define (ssigma L t)
    (<- cpt (+ cpt 1))
    (if (null? L)
      (begin #f)
      ($+>
       (<+ c (first L))
       (<+ R (rest L))
       (cond
        ((= c t) #t)
        ((> c t) (ssigma R t))
        (else (or (ssigma R (- t c)) (ssigma R t))))))))

and if then i simply edit the code and remove the 'module' directive:

 (require "../Scheme+.rkt")
  (<+
   L-init
   '(1
     3
     4
     16
     17
     24
     45
     64
     197
     256
     275
     323
     540
     723
     889
     915
     1040
     1041
     1093
     1099
     1111
     1284
     1344
     1520
     2027
     2500
     2734
     3000
     3267
     3610
     4285
     5027))
  (<+ t-init 35267)
  (<+ cpt 0)
  (define (ssigma L t)
    (<- cpt (+ cpt 1))
    (if (null? L)
      (begin #f)
      ($+>
       (<+ c (first L))
       (<+ R (rest L))
       (cond
        ((= c t) #t)
        ((> c t) (ssigma R t))
        (else (or (ssigma R (- t c)) (ssigma R t)))))))

it can not works in the Racket GUI code frame but if i load the code in REPL of (Racket ,supposing this is the default language) it then works:

Welcome to DrRacket, version 8.11 [cs].
Language: racket, with debugging; memory limit: 8192 MB.
> (load "Scheme-PLUS-for-Racket/main/Scheme-PLUS-for-Racket/examples/SssRec.rkt")
> t-init
35267
> (set! t-init 7)
> t-init
7

i will then add an option in my parser curly-infix2prefix4racket.rkt to disable the encapsulation of code in a module.

thanks

Damien

note: it worked in Guile because the parser does not generate a module...