9.2 Impact of mutation
Introducing assignment presents many complications for our programming model. It invalidates the substitution model of evaluation introduced in Section 3.6.2 and found satisfactory until this point. All the procedures we can define without using mutation behave almost like mathematical functions---every time they are applied to the same inputs they produce the same output.1Assignments allow us to define non-functional procedures that produce different results for different applications even with the same inputs.
(set! counter (+ counter 1))
update-counter!, we must first define the
counter variable it uses:
(update-counter!) is evaluated the value associated with the name
counter is increased by one and the result is the new value of counter. Because of the hidden begin expression in the definition, the
(set! counter (+ counter 1)) is always evaluated first, followed by
counter which is the last expression in the begin expression so its value is the value of the procedure. Thus, the value of
1 the first time it is evaluated,
2 the second time, and so on.
The substitution model of evaluation doesn't make any sense for this evaluation: the value of
counter changes during the course of the evaluation. Even though
(update-counter!) is the same expression, every time it is evaluated it evaluates to a different value.
Mutation also means some expressions have undetermined values. Consider evaluating the expression
(+ counter (update-counter!)). The evaluation rule for the application expression does not specify the order in which the operand subexpressions are evaluated. But, the value of the name expression
counter depends on whether it is evaluated before or after the application of
update-counter! is evaluated!
The meaning of the expression is ambiguous since it depends on the order in which the subexpressions are evaluated. If the second subexpression,
counter, is evaluated before the third subexpression,
(update-counter!), the value of the expression is
1 the first time it is evaluated, and
3 the second time it is evaluated. Alternately, but still following the evaluation rules correctly, the third subexpression could be evaluated before the second subexpression. With this ordering, the value of the expression is
2 the first time it is evaluated, and
4 the second time it is evaluated.