无法在SICP ex-1.37中将lambda表达式计算为参数

时间:2014-01-12 06:46:28

标签: scheme sicp

问题可以在http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_thm_1.37

找到

问题是扩展连续分数以接近phi。它表明您的程序应该能够通过评估来计算phi:

(cont-frac (lambda (i) 1.0)
           (lambda (i) 1.0)
           k)

我的解决方案如下:

(define (cont-frac n d k)
 (if (= k 1) d
     (/ n (+ d (cont-frac n d (- k 1))))))

此解决方案在调用(cont-frac 1 1 k)时有效,但在问题表明使用lambda表达式时则无效。我得到的是类型错误

;ERROR: "ex-1.37.scm": +: Wrong type in arg1 #<CLOSURE <anon> (x) 1.0>
; in expression: (#@+ #@d (#@cont-frac #@n #@d (#@- #@k 1)))
; in scope:
;   (n d k)  procedure cont-frac
; defined by load: "ex-1.37.scm"

;STACK TRACE
1; ((#@if (#@= #@k 1) #@d (#@/ #@n (#@+ #@d (#@cont-frac #@n #@d  ...

我的问题分为两部分:

问题1.为什么在使用lambda参数时出现此错误?我(错误地,当然)认为(lambda(x)1)应该评估为1.它显然不是。我不确定我是否理解它所评估的内容:我认为它没有评估任何东西(即,“返回一个值” - 可能是错误的术语),而不是传递x的参数。

为什么你会有一个返回常量的lambda,仍然没有回答。如果我理解正确,(lambda(x)1.0)将始终评估为1.0,无论x是什么。那么为什么不放1.0呢?这导致:

问题2.我为什么要使用它们?我怀疑这在ex-1.38中是有用的,我已经看过了,但我不明白为什么使用(lambda(x)1.0)与使用1.0的任何不同。

2 个答案:

答案 0 :(得分:2)

在Scheme lambda中,表达式创建一个函数,因此表达式如:

(lambda (i) 1.0)

确实有结果,它是一个功能对象。 但是如果你在该表达式周围添加括号,它确实将按照你的预期评估为1.0

((lambda (i) 1.0))

在练习中使用lambdas对于构建通用解决方案是必要的,正如您在练习1.38中正确注意到的那样,您将使用cont-frac函数的相同实现,但具有不同的分子和分母函数,以及你会看到一个例子,你应该在运行时使用循环计数器来计算其中一个。

你可以将你的运动解决方案与我的比较,例如1.371.38

答案 1 :(得分:0)

 (/ n (+ d (cont-frac n d (- k 1))))))

在这种情况下,'d'是lambda语句,对'+'没有任何意义,对'n'和'/'也是如此

 (/ (n k) (+ (d k) (cont-frac n d (- k 1))))))

你会明白为什么在下一个练习中你也可以使这个尾递归

我将变量命名为F-d和F-n而不是d和n,因为它们接受一个计算分子和分母项的函数。 (lambda(i)1.0)是一个接受一个参数并返回1.0的函数,1.0只是一个数字。在其他连续分数中,该值可能随深度而变化(因此您需要将k传递给分子和分母函数来计算正确的项。