关于Lisp中正则序和应用序的问题,练习1.5,1.6,1.20

关于正则序和应用序的问题,贯穿了全书,中间的习题和后面的惰性求值都会涉及到。

书上已经给出了明确的定义:正则序是:完全展开后规约,应用序是:先求值而后应用。

以练习1.5为例,

(define (p) (p))
(define (test x y)
   (if (= x 0)
       0
       y))
(test 0 (p))

使用正则序(直接将参数代入而不求值),会将这个过程展开为,因为满足if条件,于是直接返回0

(if (= 0 0)
    0
   (p))

使用应用序(先求参数(p)),于是,你懂的,它自废武功死了,一般我们使用的解释器环境就是应用序,所以,这段程序运行就挂了。


无独有偶,练习1.6同样考察了这个问题,

(define (sqrt-iter guess x)
  (new-if (good-enough? guess x)
               guess
               (sqrt-iter (improve guess x)
                               x)))

由于我们的解释器就是应用序,所以这个new-if在展开前先会求解后面的参数,当求解到sqrt-iter时,悲剧又发生了,它又不断的递归展开参数,所以不能使用cond替代if


1.20再次提到这个问题

如果按照正则序展开,会变成如下的序列,展开时候if求值用了14次(a1 + a2 + a3 + a4 = a1 + (a1 + 1) + (a1 + a2 + 1) + (a2 + a3 + 1)),而归约时又用了4次,所以总共18次

gcd(206 40)
if(= 40 0)
gcd(40 (remainder 206 40));a1=(remainder 206 40)
if(= a1 0)
gcd(a1 (remainder 40 a1));a2=(remainder 40 a1)
if(= a2 0)
gcd(a2 (remainder a1 a2));a3=(remainder a1 a2)
if(= a3 0)
gcd(a3 (remainder a2 a3));a4=(remainder a2 a3)
if(= a4 0);a4=0
归约过程
(remainder a1 a2)
(remainder (remainder 206 40) (remainder 40 (remainder 206 40)))
(remainder 6 (remainder 40 6))
(remainder 6 4)
2


如果按照应用序,则求值时候共用了4次

gcd(40 6)
gcd(6 4)
gcd(4 2)
gcd(2 0)

所以一方面也可以明白为什么大多解释器用应用序而不是正则序



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值