I have a simple program:
(import (rnrs))
(define (abs x)
(cond ((> x 0) x)
((= x 0) 0)
((< x 0) (- x))
))
(define (square x)
(* x x))
(define (sum-sq x y)
(+ (square x) (square y)))
(display
(sum-sq (read) 3))
When I run it, I have an exception; what did I do wrong?
/home# scheme-script /home/scheme/main.ss
Exception: multiple definitions for abs in body (top-level-program #<annotation /home/scheme/main.ss[0:15] (import (...))> #<annotation /home/scheme/main.ss)[17:122] (define (...) (...))> #<annotation /home/scheme/main.ss[124:156] (define (...) (...))> #<annotation /home/scheme/main.ss[158:210] (define (...) (...))> #<annotation /home/scheme/main.ss[212:244] (display (...))> near line 1, char 1 of /home/scheme/main.ss
It is illegal to redefine a variable in a top-level program in R6RS Scheme. OP has executed the script using
scheme-script; in Chez Schemescheme-scriptis equivalent toscheme --program, which treats the file as a top-level program. It is fine to redefine things in the REPL when you are experimenting with definitions, unless you wrap that code in atop-level-programform.scheme --scripttreats the file as a shell script, whilescheme-script(i.e.,scheme --program) treats it as a top-level program. To demonstrate that OP's problem is a result of the file being treated as a top-level program, run it usingscheme --script, then wrap the posted code in a(top-level-program ...)form and try running again withscheme --script. The first attempt will execute successfully, and the second will again raise an exception.One solution to OP's problem is to use
scheme --scriptinstead ofscheme-script(orscheme --program). Of course, one could simply use the built-inabsprocedure, or rename the new procedure as, e.g.,my-abs.But, sometimes you really do want to use an identifier that has previously been claimed by some library that you need to import. For that situation there is
except. Here is a version of OP's code usingexceptin theimportform:This program imports all identifiers which are exported from the
rnrslibrary, except forabs. The top-level program is then free to define anabsidentifier.What the Standard Says
A top-level program is like a library, except that it cannot contain
exportforms. From R6RS 7.1. Library form:The specification continues:
But, by 11.4.6. Binding constructs, in a
letrec*form:So an identifier can't be imported multiple times, both imported and defined, or defined and redefined in a library or top-level program. The OP code violates this by both importing a definition for an identifier, and redefining that identifier within the top-level program.