When evaluating and calling 'set-variable-value!' and 'define-variable-value!', the program will pass 'env' to the function, and in these two functions, 'set!' can only modify the 'env' which is inside the function; the modified 'env' is not returned as well.
So, how can the 'env' be changed?
Remember that in the book, in section 3.3, Modeling with Mutable Data, mutable operators are introduced, by using the convention of suffixing the function name with !
, like in set-car!
, that modifies the car of a cons cell.
The functions set-variable-value!
and define-variable-value!
simply modify the passed environment, so that there is no need to return it. For instance, set-variable-value!
is defined through the use of set-car!
:
(define (set-variable-value! var val env)
(define (env-loop env)
(define (scan vars vals)
(cond ((null? vars)
(env-loop (enclosing-environment env)))
((eq? var (car vars))
(set-car! vals val))
(else (scan (cdr vars) (cdr vals)))))
(if (eq? env the-empty-environment)
(error "Unbound variable -- SET!" var)
(let ((frame (first-frame env)))
(scan (frame-variables frame)
(frame-values frame)))))
(env-loop env))
Note that the authors, at the beginning of Chapter 4, say:
The language implemented by our evaluator will be a subset of the Scheme dialect of Lisp that we use in this book.
And since the dialect introduced has side-effects, the simplest solution to implement it is to use side-effects also in its interpreter.