Little Schemer:为什么要把(mk-length mk-length) 包装成一个函数?
Little Schemer: why wrap (mk-length mk-length) into a function?
在The Little Schemer book, in Chapter 9, while building a length
function for arbitrary long input, the following is suggested (on pages 170-171), that in the following code snippet (from page 168本身):
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
((lambda (length)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l)))))))
(mk-length mk-length))))
部分 (mk-length mk-length)
永远不会 return 并且会无限地应用于自身:
Because we just keep applying mk-length
to itself again and again and again...
和
But now that we have extracted (mk-length mk-length)
from the function that makes length
it does not return a function anymore.
现在,要解决这个问题,本书建议:
Turn the application of mk-length
to itself in our last correct version of length
into a function.
喜欢,所以:
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
((lambda (length)
(lambda (l)
(cond
((null? l) 0 )
(else
(add1 (length (cdr l)))))))
(lambda (x)
((mk-length mk-length) x)))))
我比较疑惑的是:
如果(mk-length mk-length)
does not return a function
我们如何将 (mk-length mk-length)
的结果应用到某个东西上,就像它是一个函数一样?
(lambda (x)
((mk-length mk-length) x))
如何将 (mk-length mk-length)
包装到一个函数中来解决 'never returning'(即无限递归)问题?我的理解是,在:
(lambda (x)
((mk-length mk-length) x))
x
将被传递给无限递归函数,永远不会 returns。
这次通话
(mk-length mk-length)
只会调用 mk-length
一次。
如果mk-length
恰好调用它自己,那么mk-length
的主体将
再次被评估——但 mk-length
并不总是调用自己。
至于为什么——请注意您的表达式中没有函数使用 define
命名。所有函数表达式都使用 lambda
来引入匿名函数。
例子表明,即使只使用匿名函数,也可以编写递归函数。函数不是直接命名函数(使用 define
),而是作为参数传递给另一个函数——并且该函数为其参数命名。
您可能复制了错误的代码片段,即您实际谈论的代码片段之前的那个。您显示的第一个代码完全没问题。循环是什么,而是这个:
((lambda (mk-length)
(mk-length mk-length)) ; (1)
(lambda (mk-length)
((lambda (length) ; (2)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l))))))) ; (4)
(mk-length mk-length)))) ; (3)
已经回答here:应用程序(1)
触发应用程序(2)
,应用程序(2)
立即触发应用程序(3)
,相当于(1)
!因此,循环。
将其包装在 lambda(又名 eta-expansion)中会延迟应用程序 (3)
,直到在 [= 中调用构造的 length
18=],完全没问题(你复制的也有一些错别字):
((lambda (mk-length)
(mk-length mk-length)) ; (1)
(lambda (mk-length) ; (5)
((lambda (length) ; (2)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l))))))) ; (4)
(lambda (x) ; (3)
(mk-length mk-length) x))))
(3)
现在是一个 lambda 表达式,而不是一个应用程序。评估此 lambda 表达式会生成一个匿名函数。此 lambda 函数 将 执行应用程序 (mk-length mk-length)
稍后 ,当 length
被调用时。
(更长的解释:)
(3)
只是 returns 立即绑定到 length
的 lambda 函数,并且 (lambda (l) ...)
很高兴返回,这样当 that (lambda (l) ...)
将应用于某些列表,可能导致此length
1在(4)
中被调用,只有 then lambda (3)
中的应用程序 (mk-length mk-length)
才会真正执行——最终给我们新的 (lambda (l) ...)
匿名函数,它将被应用到(cdr l)
那里。
1length
是 (lambda (x) ((mk-length mk-length) x))
这意味着 (length (cdr l))
与 ((mk-length mk-length) (cdr l))
相同(mk-length
绑定到整个 lambda 表达式 (5)
),最终 ((lambda (l) ...) (cdr l))
.
妮娜
在The Little Schemer book, in Chapter 9, while building a length
function for arbitrary long input, the following is suggested (on pages 170-171), that in the following code snippet (from page 168本身):
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
((lambda (length)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l)))))))
(mk-length mk-length))))
部分 (mk-length mk-length)
永远不会 return 并且会无限地应用于自身:
Because we just keep applying
mk-length
to itself again and again and again...
和
But now that we have extracted
(mk-length mk-length)
from the function that makeslength
it does not return a function anymore.
现在,要解决这个问题,本书建议:
Turn the application of
mk-length
to itself in our last correct version oflength
into a function.
喜欢,所以:
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
((lambda (length)
(lambda (l)
(cond
((null? l) 0 )
(else
(add1 (length (cdr l)))))))
(lambda (x)
((mk-length mk-length) x)))))
我比较疑惑的是:
如果
(mk-length mk-length)
does not return a function
我们如何将
(mk-length mk-length)
的结果应用到某个东西上,就像它是一个函数一样?(lambda (x) ((mk-length mk-length) x))
如何将
(mk-length mk-length)
包装到一个函数中来解决 'never returning'(即无限递归)问题?我的理解是,在:(lambda (x) ((mk-length mk-length) x))
x
将被传递给无限递归函数,永远不会 returns。
这次通话
(mk-length mk-length)
只会调用 mk-length
一次。
如果mk-length
恰好调用它自己,那么mk-length
的主体将
再次被评估——但 mk-length
并不总是调用自己。
至于为什么——请注意您的表达式中没有函数使用 define
命名。所有函数表达式都使用 lambda
来引入匿名函数。
例子表明,即使只使用匿名函数,也可以编写递归函数。函数不是直接命名函数(使用 define
),而是作为参数传递给另一个函数——并且该函数为其参数命名。
您可能复制了错误的代码片段,即您实际谈论的代码片段之前的那个。您显示的第一个代码完全没问题。循环是什么,而是这个:
((lambda (mk-length)
(mk-length mk-length)) ; (1)
(lambda (mk-length)
((lambda (length) ; (2)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l))))))) ; (4)
(mk-length mk-length)))) ; (3)
已经回答here:应用程序(1)
触发应用程序(2)
,应用程序(2)
立即触发应用程序(3)
,相当于(1)
!因此,循环。
将其包装在 lambda(又名 eta-expansion)中会延迟应用程序 (3)
,直到在 [= 中调用构造的 length
18=],完全没问题(你复制的也有一些错别字):
((lambda (mk-length)
(mk-length mk-length)) ; (1)
(lambda (mk-length) ; (5)
((lambda (length) ; (2)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l))))))) ; (4)
(lambda (x) ; (3)
(mk-length mk-length) x))))
(3)
现在是一个 lambda 表达式,而不是一个应用程序。评估此 lambda 表达式会生成一个匿名函数。此 lambda 函数 将 执行应用程序 (mk-length mk-length)
稍后 ,当 length
被调用时。
(更长的解释:)
(3)
只是 returns 立即绑定到 length
的 lambda 函数,并且 (lambda (l) ...)
很高兴返回,这样当 that (lambda (l) ...)
将应用于某些列表,可能导致此length
1在(4)
中被调用,只有 then lambda (3)
中的应用程序 (mk-length mk-length)
才会真正执行——最终给我们新的 (lambda (l) ...)
匿名函数,它将被应用到(cdr l)
那里。
1length
是 (lambda (x) ((mk-length mk-length) x))
这意味着 (length (cdr l))
与 ((mk-length mk-length) (cdr l))
相同(mk-length
绑定到整个 lambda 表达式 (5)
),最终 ((lambda (l) ...) (cdr l))
.
妮娜