SICP练习1.15:求值时操作数是否先于运算符被求值?
SICP sine过程递归问题解答
题目涉及代码
(define (cube x) (* x x x)) (define (p x) (- (* 3 x) (* 4 (cube x)))) (define (sine angle) (if (not (> (abs angle) 0.1)) angle (p (sine (/ angle 3.0)))))
题目问题a为:求值(sine 12.15)时过程p会被应用多少次?
常见推导过程如下:
(sine 12.15) (p (sine 4.05)) (p (p (sine 1.35))) (p (p (p (sine 0.45)))) (p (p (p (p (sine 0.15))))) (p (p (p (p (p (sine 0.05)))))) (p (p (p (p (p 0.05)))))
按照该推导,p总共会被调用5次。
疑问解答
该推导逻辑完全符合Scheme的求值规则,核心依据就是Scheme默认采用**应用序(Applicative Order)**求值:
- 对组合式求值时,解释器会先完成所有子表达式(运算符、全部操作数)的求值,再将运算符对应的过程应用到求值完成的实际参数上。
你提到的“执行到(p (sine 4.05))时先展开p再递归”的思路,属于正则序(Normal Order)的求值逻辑——即先完全展开所有过程调用,直到表达式只剩原生基本操作时再开始计算,Scheme并不采用这种规则。
具体到(p (sine 4.05))的求值步骤,执行顺序为:
- 求值运算符
p,得到预先定义的对应过程 - 求值操作数
(sine 4.05):递归进入sine过程定义,持续将角度除以3并判断阈值,直到递归触底返回0.05这个确定值,再逐层向外返回计算结果,每向外返回一层就触发一次p的调用 - 等操作数完全求值得到确定数值后,才会将该值传入p的过程体,执行p内部的乘法、减法计算。
正是因为应用序“参数求值完成后才调用过程”的特性,直接计数推导式中嵌套的p的层数,就能得到p的准确调用次数,不需要考虑p提前展开带来的额外调用。
内容的提问来源于stack exchange,提问作者Pharrio
相关产品推荐
相关产品推荐

