In Scheme, what's the point of "set!"?

HS. picture HS. · Feb 8, 2009 · Viewed 21k times · Source

What's the point of using the set! assignment operator in scheme? Why not just rebind a variable to a new value using define?

> (define x 100)
> (define (value-of-x) x) ;; value-of-x closes over "x"
> x
100
> (value-of-x)
100
> (set! x (+ x 1))
> x
101
> (value-of-x)
101
> (define x (+ x 1))
> x
102
> (value-of-x)
102
> 

Answer

Kyle Cronin picture Kyle Cronin · Feb 8, 2009

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 defined 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 defines, and some won't. Also, you're only supposed to use set! on a variable that's already been defined. Again, how strictly this rule is enforced depends on the implementation.