帮助理解计划中的延续
-
19-09-2019 - |
题
我一直在工作 小计划 学习方案并将PLT-Scheme用于我的环境。
小计划 对我的递归极大地帮助了我(现在对我来说很简单),但是我陷入了介绍“收藏家”的一部分,并将整个功能称为延续。
这是他们使用的示例代码。我了解递归元素,但我被卡住了,尤其是在lambda函数上 - 我的头脑无法遵循路径以及如何设置该lambda函数的论点(因为他们唯一的呼吁是在递归中再次称呼它们,所以有功能主体中没有具体使用)。
如果某人或者可以通过将功能递归递归到lambda收集器中,从而使我对计算道路进行分解,那可能会对我有所帮助。
;; Build a nested list of even numbers by removing the odd ones from its
;; argument and simultaneously multiply the even numbers and sum the odd
;; numbers that occur in its argument.
(define (even-only-collector l col)
(cond
((null? l)
(col (quote ()) 1 0))
((atom? (car l))
(cond
((even? (car l))
(even-only-collector (cdr l)
(lambda (newl p s)
(col (cons (car l) newl)
(* (car l) p) s))))
(else
(even-only-collector (cdr l)
(lambda (newl p s)
(col newl
p (+ (car l) s)))))))
(else
(even-only-collector (car l)
(lambda (al ap as)
(even-only-collector (cdr l)
(lambda (dl dp ds)
(col (cons al dl)
(* ap dp)
(+ as ds)))))))))
;; The collector function
(define (collector newl product sum)
(cons sum
(cons product newl)))
先感谢您!!
解决方案
尝试更简单的事物,以了解其工作原理。例如,这是一个版本 list-sum
接收连续参数的功能(通常称为 k
):
(define (list-sum l k)
(if (null? l)
???
(list-sum (cdr l) ???)))
基本模式存在,缺少的部分是有趣的事情发生的地方。续参数是一个期望接收结果的函数 - 因此,如果列表为null,很明显我们应该发送它 0
, ,因为那是总和:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) ???)))
现在,当列表不是零的时候,我们用列表的尾巴递归将功能称为(换句话说,这是迭代),但是问题是延续是什么。这样做:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) k)))
显然是错误的 - 这意味着 k
最终将收到的总和 (cdr l)
而不是所有 l
. 。相反,在那里使用新功能,该功能将总结 l
以及它收到的价值也是如此:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) (lambda (sum) (+ (car l) sum)))))
这越来越近,但仍然错了。但这是考虑事物的工作方式的好点 - 我们正在打电话 list-sum
延续本身将获得总和,并添加我们现在看到的第一项。我们忽略了这一事实,缺失的部分显而易见 k
. 。我们需要的是 撰写 k
使用此功能 - 因此我们执行相同的总和操作,然后将结果发送到 k
:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) (compose k (lambda (s) (+ s (car l)))))))
终于有效。 (顺便说一句,请记住这些 lambda
功能有其自己的“复制” l
。)您可以尝试以下方法:
(list-sum '(1 2 3 4) (lambda (x) x))
最后注意,这与:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) (lambda (s) (k (+ s (car l)))))))
如果您将构图明确。
(您还可以在中级+lambda学生语言中使用此代码,然后单击“步进”按钮以查看评估如何进行 - 这将需要一段时间才能过去,但是您将看到延续功能如何嵌套,每个功能如何用自己的列表视图。)
其他提示
这是帮助您“获得更具体的想法”的一种方法。想象一下,是否对收藏家进行了定义:
(define (collector l p s)
(display l)
(newline)
(display p)
(newline)
(display s)
(newline))
您可以在基本情况下看到,如果您传递了空列表,它将用参数调用您的功能 '()
, ,1和0。现在,使用一个元素列表,看看它将称呼您的功能。继续使用越来越长的列表,直到您弄清楚发生了什么。
祝你好运!