这个小阴谋者在page 165上给出了以下函数,因为函数 length 0 。但这是如何工作的?看起来 length lambda 被传递给 mk-length lambda ,它使用 length lambda <评估 length lambda / em>本身作为参数传递。那么,当评估底部的(length (cdr l))
时length
只是长度lambda 本身。但 length lambda 有两个参数:length
和l
。那么(length (cdr l))
怎么能理解呢?
((lambda (mk-length)
(mk-length mk-length))
(lambda (length)
(lambda (l)
(cond
((null? l) 0)
(else (add1
(length (cdr l))))))))
答案 0 :(得分:5)
Little Schemer 正在构建一个适用于越来越长的列表的函数。长度≤0的一部分是它仅适用于长度小于或等于零的列表(并且由于没有负长度列表,这意味着长度为零的列表)。您显示故意的代码仅适用于长度为零的列表。事实上,page 165中的文字甚至指出了这一点:
答:如果我们此时可以创建 mk-length 的另一个应用 eternity ,该怎么办?
B:那只会把问题推迟到一个,而且,我们怎么能这样做?
A:好吧,因为没有人关心我们传递给 mk-length 的函数,我们最初可以传递 mk-length 。
B:这是正确的想法。然后我们在 eternity 上调用 mk-length ,并在 cdr 上调用它的结果,这样我们就可以再获得一块塔。<登记/> A:然后这仍是长度 0((lambda (mk-length) (mk-length mk-length)) (lambda (length) (lambda (l) (cond ((null? l) 0) (else (add1 (length (cdr l))))))))
B:是的,我们甚至可以使用 mk-length 而不是 length :
((lambda (mk-length) (mk-length mk-length)) (lambda (mk-length) (lambda (l) (cond ((null? l) 0) (else (add1 (mk-length (cdr l))))))))
A:我们为什么要这样做?
B:所有名字都相同,但有些名字比其他名字更相等 A:是的:只要我们始终使用这些名称,我们就可以了 B: mk-length 的名称远远超过 length 。如果我们使用像 mk-length 这样的名称,则会不断提醒 mk-length 的第一个参数是 mk-length 。< / p>
在page 166上,作者显示了一个适用于长度为0或1(即≤1)的列表的版本。最后,在page 167上,他们可以使用适用于任何长度列表的版本。 的工作方式在另一个问题中有更详细的描述:
您可能还会发现以下感兴趣的问题:
eternity
函数的长度≤1 )