4.2.1 · Нормальный порядок и аппликативный порядок
Порядок вычислений и момент работы над аргументом
Одни и те же применения проходят через строгий вычислитель и немемоизированный нормальный порядок, а зонд считает работу над лишним аргументом.
Вопрос для размышления
Как два вычислителя могут возвращать одно и то же значение, выполняя при этом разный объем работы с аргументами?
Вычисление каждого операнда перед строгим составным применением
Связывание невычисленных выражений операндов как thunk нормального порядка
Форсирование thunk только тогда, когда поиск переменной требует ее значение
Наблюдение неиспользуемого аргумента при обеих стратегиях
Наблюдение дублирования работы при двукратном обращении к параметру нормального порядка
Сравнение двух явных стратегий вычисления guest
Процедура strict-eval вычисляет операнд перед применением составной процедуры. Поэтому игнорируемый аргумент x вызывает probe один раз, даже если тело возвращает 1. Процедура normal-eval вместо этого связывает x с thunk, содержащим выражение операнда и его окружение. Поскольку тело никогда не выполняет поиск x, процедура probe не запускается.
Во втором выражении тело использует x дважды. Строгое вычисление выполняет probe один раз и связывает полученное значение 10. Немемоизированный вычислитель нормального порядка форсирует сохраненное выражение при каждом поиске, поэтому probe запускается дважды. Оба возвращают 20, но объем работы различается. Эти два вычислителя представляют собой явные модели guest, и они не меняют порядок вычислений выполняющей их программы хоста Lispex.
Программа возвращает ((unused (1 1) (1 0)) (duplicated (20 1) (20 2))). Каждая пара содержит значение, за которым следует количество вызовов probe.
На что обратить внимание в трассе
В strict-eval найдите вызов probe до начала выполнения составного тела. В normal-eval проследите за каждым связыванием параметра с thunk и убедитесь, что оно форсируется только при поиске переменной. Неиспользуемое тело не выполняет форсирование, а тело с дублированием обращается к одному и тому же выражению thunk дважды, поскольку эта модель намеренно не выполняет мемоизацию.
Попробуйте сами
Измените программу и сравните результат.
Добавьте ((lambda (x) (+ x (+ x x))) (probe 4)). Спрогнозируйте количество вызовов probe для строгого вычисления и нормального порядка, а затем добавьте ячейку мемоизации в thunk и спрогнозируйте количество вызовов при вызове по необходимости.
Показать подсказку
Строгое вычисление вычисляет аргумент один раз. Немемоизированный нормальный порядок выполняет вычисление один раз на каждый поиск x. Мемоизированный thunk вычисляет значение не более одного раза.