Я медленно прокладывал себе путь хотя упражнения в Структуре и Интерпретация Компьютерных программ. Разделите 1.1.5 переговоров о применимом по сравнению с оценкой нормального порядка, и тема подходила несколько раз в тексте позже. Так как интерпретатор использует оценку применимого порядка, легко просто вставить display
операторы отладки в Вашем коде для наблюдения точно, как это работает. Это помогло бы моему пониманию смочь сделать то же самое для оценки нормального порядка.
Кто-либо знает Схемы (или Lisp) интерпретатор, это реализовало оценку нормального порядка использования вместо применимого порядка?
Вот короткий пример, измененный от один данный в SICP. Я определю свое собственное add
процедура, чтобы распечатать аргументы и использовать square
процедура из книги.
(define (add x y)
(display x)
(display y)
(newline)
(+ x y))
(define (square x) (* x x))
Теперь, если я запускаю короткую программу (square (add 1 2))
с помощью оценки применимого порядка, результата (add 1 2)
будет только вычислен когда-то затем передал square
процедура. Операнды 12
должен быть распечатан однажды конечный результат. Мы можем просто выполнить это в интерпретаторе, чтобы проверить, что это - то, что происходит.
> (square (add 1 2))
12
9
Используя оценку нормального порядка, тем не менее, единственный операнд (add 1 2)
должен быть скопирован в square
процедура, которая оценила бы как (* (add 1 2) (add 1 2))
. Операнды 12
должен быть распечатан дважды перед конечным результатом.
Я хотел бы смочь выполнить это в интерпретаторе, который делает оценку нормального порядка, чтобы проверить, что это действительно, как она работает.
Racket имеет ленивый язык . Это лучше, чем просто интерпретатор, поскольку вы можете писать программы, состоящие из простых модулей рэкет и ленивых.
Что касается отладки с использованием распечаток - вы можете сделать это на этом ленивом языке, и вы получите что-то похожее на небезопасный ввод-вывод в Haskell. Хотя иногда это все еще может сбивать с толку. (И если вы хотите, чтобы интерпретатор вставлял в него распечатки, это также сбивало с толку, потому что это следует за ленивым вычислением ...)
Оказывается, в Scheme уже есть оценщик нормального порядка. Это те легендарные макросы, о которых вы, наверное, так много слышали, и мы можем переписать примеры из разделов 1.1.4–1.1.5, чтобы довольно легко использовать расширение макроса вместо применения процедуры:
(define (print . items) (for-each display items)) (define-macro (add x y) `(begin (print "[ADD " ',x " " ',y "]") (+ ,x ,y))) (define-macro (mul x y) `(begin (print "[MUL " ',x " " ',y "]") (* ,x ,y))) (define-macro (square x) `(begin (print "[SQUARE " ',x "]") (mul ,x ,x))) (define-macro (sum-of-squares x y) `(begin (print "[SUM-OF-SQUARES " ',x " " ',y "]") (add (square ,x) (square ,y)))) (define-macro (f a) `(begin (print "[F " ',a "]") (sum-of-squares (add ,a 1) (mul ,a 2))))
Игнорируйте PRINT, их логика немного выходит за рамки того, где вы находитесь в тексте, но они просто сокращение для множества ДИСПЛЕЕЙ. Фактически, вы могли бы полностью отказаться от трассировки путем печати в пользу использования функции макрорасширения системы. но это зависит от реализации (например, в Ypsilon вы должны использовать (macro-expand '(f 5))
).
Если вы загрузите эти определения (с оговоркой, что DEFINE-MACRO нестандартен, но на практике это не должно быть проблемой, так как большинство схем предоставляют его), то выполняется оценка (f 5)
как и книга, будет распечатана (конечно, я ее немного приподнял):
[F 5] [SUM-OF-SQUARES (add 5 1) (mul 5 2)] [ADD (square (add 5 1)) (square (mul 5 2))] [SQUARE (add 5 1)] [MUL (add 5 1) (add 5 1)] [ADD 5 1] [ADD 5 1] [SQUARE (mul 5 2)] [MUL (mul 5 2) (mul 5 2)] [MUL 5 2] [MUL 5 2] 136
Что более или менее похоже на то, что книга иллюстрирует этот процесс.
Написание макросов такого типа в основном похоже на написание обычной процедуры, за исключением того, что
Это Написание макросов схемы 101.
В общем, это немного глупо - устанавливать макросы на кого-то только в первой главе SICP.Но если вы говорите, что вам непомерно сложно модифицировать Racket для выполнения того, что вы хотите (а есть те, кто вообще не использует Racket), то вот альтернатива.