我在学习 SICP 时读到了“应用顺序”和“正常顺序”。然后我尝试了练习 1-6 并研究了以下代码:
#lang racket
(define (p) (p))
(define (new-if test-expr then-expr else-expr)
(cond (test-expr then-expr)
(else else-expr)))
当我评估
(new-if (= 2 2) 5 (p))
时,它会进入死循环,因为 (= 2 2)
和 (p)
都被评估。所以我想知道如何按正常顺序制作这个 new-if
而不将 #lang racket
更改为 #lang lazy
,但我无法弄清楚。
> (new-if (= 2 2) 5 (p))
> 5
如果我们将
new-if
定义为函数:
(define (new-if test-expr then-expr else-expr)
...)
然后在程序中
(define (p) (p))
(new-if (= 2 2) 5 (p))
形式
(new-if (= 2 2) 5 (p))
是一个函数调用。
函数调用(按正常顺序)按以下顺序进行评估:
new-if
(评估我们的 new-if
程序)(= 2 2)
(评估为true
)5
(评估为5
)(p)
(导致循环)new-if
的结果(2.、3. 和 4. 的结果)。问题当然是我们永远不会达到 5。
(p)
的求值会导致new-if
的主体被求值之前无限循环。这意味着,无论我们在
new-if
的主体中放入什么,调用
(new-if (= 2 2) 5 (p))
总是会导致无限循环。换句话说,在具有正常顺序语义的语言中,您无法将
new-if
定义为正常函数。
(new-if e0 e1 e2)
的预期评估顺序是:
e0
,我们将结果称为
t
。
t
非假,则评估
e1
t
是假的,所以评估
e2
new-if
必须定义为新形式。定义表单的机制 使用非标准评估顺序是
define-syntax
。它可以让你 将
new-if
定义为宏。