
3.2. Моде ль вычислений с окружениями
231
• Процедура создается при вычислении lambda-выражения по отношению к некото-
рому окружению. Получающийся процедурный объект есть пара, состоящая из текста
lambda-выражения и указателя на окружение, в котором процедура была создана.
Кроме того, мы указываем, что когда символ определяется при помощи define,
в текущем кадре окружения создается связывание, и символу присваивается указан -
ное значение
13
. Наконец, мы описываем поведение set!, операции, из-за которой нам,
собственно, и пришлось ввести модель с окружениями. Вычисление выражения (set!
hпеременнаяi hзначениеi) в некотором окружении заставляет интерпр етатор найти
связывание переменной в окружении и изменить это связывание так, чтобы оно ука-
зывало на новое значение. А именно, нужно найти первый к адр окружения, в котором
содерж ится связывание для переменной, и изменить этот кадр. Если переменная в окру-
жении не связана, set! сигнализирует об ошибке.
Все эти правила вычисления, хотя они значительно сложнее, чем в подстановочной
модели, достаточно просты. Более того, модель вычислений, несмотря на свою абстракт-
ность, дает правильное описание того, как интерпретатор вычисляет выражения. В гла-
ве 4 мы увидим, как эта модель може т служить основой для реализации работающего
интерпретатора. В последующих разделах анализ нескольких примеров программ рас-
крывает некоторые детали этой модели.
3.2.2. Применение простых процедур
Когда в разделе 1.1.5 мы описывали подстановочную модель, мы показали, как вы-
числение комбинации (f 5) дает резул ьтат 136, если даны следующие определения:
(define (square x)
(* x x))
(define (sum-of-squares x y)
(+ (square x) (square y)))
(define (f a)
(sum-of-squares (+ a 1) (* a 2)))
Теперь мы можем проанализировать тот же самый пример, используя модель с окруже-
ниями. На рисунке 3.4 изображены три процедурных объекта, созданные вычислением
в глобальном окружении определений f, square, и sum-of-squares. Каждый проце-
дурный объект состоит из куска кода и указателя на глобальное окружение.
На рисунке 3.5 мы видим структуру окружений, созданную вычислением выражения
(f 5). Вызов f создает новое окружение E1, начинающееся с кадра, в котором a,
формальный параметр f, связывается с аргументом 5. В окружении E1 мы вычисляем
тело f:
(sum-of-squares (+ a 1) (* a 2))
13
Если в текущем кадре уже имелось связывание для указанной переменной, то это связывание изменяет-
ся. Это правило удобно, поскольку позволяет переопределять символы; однако оно означает, что при помощи
define можно изменять значение символов, а это влечет за собой все проблемы, связанные с присваиванием,
без явного использования set!. По этой причине некоторые предпочитают, чтобы переопределение существу-
ющего символа вызывало предупреждение или сообщение об ошибке.