Явная локальная инициализация внутренних имен
Тело процедуры сначала размещает каждое внутреннее имя, затем задает значения присваиванием, поэтому взаимно рекурсивные процедуры делят одно окружение.
Почему вычислитель должен создать все внутренние связывания до того, как установит какие-либо значения процедур?
- Распознавание начальных внутренних определений в теле процедуры
- Преобразование синтаксиса определения процедуры в явное значение lambda
- Размещение каждого локального имени с маркером unassigned перед присваиванием
- Сохранение исходного тела без определений после присваиваний
- Сравнение исходной и преобразованной программ на одинаковых конечных входных данных
- Проверка согласованности для показанного преобразования и входных данных
Проход scan-out считывает тело процедуры как данные. Он берет начальные формы define, преобразует сокращенную запись определения процедуры в выражения lambda, создает одно связывание let для каждого имени с явным маркером unassigned и помещает set! для каждого определения перед исходным оставшимся телом. Таким образом, имена существуют вместе до применения любого замыкания, что дает взаимно рекурсивным вспомогательным процедурам одно общее локальное окружение.
Вторая программа выполняет обе формы. classify-original использует внутренние определения напрямую. classify-scanned явно записывает преобразованную структуру let и set!. Обе формы возвращают одинаковые результаты проверки четности для 7 и 8, и equal? возвращает true. Конечное сравнение проверяет это преобразование и делает видимой его явную промежуточную структуру.
- Вывод
- —
- Значение
- —
- Диагностика
- —
Программа преобразования возвращает одно выражение let с even-step и odd-step, связанными с цитированными маркерами *unassigned*, за которыми следуют две формы set! и исходное тело списка. Программа сравнения возвращает (#t ((#f #t) (#t #f)) ((#f #t) (#t #f))).
В запуске преобразования отделите чтение цитированных данных исходного кода от сбора начальных определений, построения связываний, преобразования определений процедур в значения lambda, построения присваиваний и присоединения оставшегося тела. В запуске сравнения найдите одно окружение let, обе операции set! и чередующиеся вызовы замыканий. Согласованность сообщается только для выбранных входных данных.
Измените программу и сравните результат.
Добавьте третью внутреннюю вспомогательную процедуру, которая распознает значения, делящиеся на три, с помощью трех взаимно рекурсивных процедур для остатка. Напишите как исходную, так и явно преобразованную версию scan-out, затем сравните их результаты для 8 и 9.
Показать подсказку
Разместите все три имени перед присваиваниями. Каждое замыкание вызывает следующую процедуру остатка после вычитания единицы, и только процедура нулевого остатка возвращает true при нуле.