Though both define
and set!
will redefine a value when in the same scope, they do two different things when the scope is different. Here's an example:
(define x 3)
(define (foo)
(define x 4)
x)
(define (bar)
(set! x 4)
x)
(foo) ; returns 4
x ; still 3
(bar) ; returns 4
x ; is now 4
As you can see, when we create a new lexical scope (such as when we define
a function), any names defined within that scope mask the names that appear in the enclosing scope. This means that when we define
d x
to 4
in foo
, we really created a new value for x
that shadowed the old value. In bar
, since foo
does not exist in that scope, set!
looks to the enclosing scope to find, and change, the value of x
.
Also, as other people have said, you're only supposed to define
a name once in a scope. Some implementations will let you get away with multiple define
s, and some won't. Also, you're only supposed to use set!
on a variable that's already been define
d. Again, how strictly this rule is enforced depends on the implementation.