Search code examples
schemesicp

SICP:'set' and 'define' in The Metacircular Evaluator


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?


Solution

  • 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.