Functional programming 在scheme中转换具有两个递归调用的函数,使其成为尾部递归函数
在我开始之前:是的,这是大学的家庭作业。在我被告知我懒惰和邪恶之前:家庭作业的这一部分是转换我们已经拥有的两个函数,这是第六个Functional programming 在scheme中转换具有两个递归调用的函数,使其成为尾部递归函数,functional-programming,scheme,tail-recursion,Functional Programming,Scheme,Tail Recursion,在我开始之前:是的,这是大学的家庭作业。在我被告知我懒惰和邪恶之前:家庭作业的这一部分是转换我们已经拥有的两个函数,这是第六个 (define (flatten-list a-list) (cond ((null? a-list) '()) ((list? (car a-list)) (append (flatten-list (car a-list)) (flatten-list (cdr a-list)))) (else (cons (car a-
(define (flatten-list a-list)
(cond ((null? a-list) '())
((list? (car a-list))
(append (flatten-list (car a-list)) (flatten-list (cdr a-list))))
(else (cons (car a-list) (flatten-list (cdr a-list))))))
正如您所猜测的那样,该函数会使列表变平,即使它是嵌套的。我对转换的具体问题出现在(list?(cara-list))条件中,在该条件下,我正在执行两个递归调用。我已经做了斐波那契,我可以通过在尾部递归上有两个“acummulator”来完成。然而,我的头脑还没有接受过这方面的训练,还不知道该怎么做
如果给我提示而不是结果,我将不胜感激。谢谢 以下是我的解决方案:
(define (flatten-iter a-list)
(define (flat-do acc lst-interm lst)
(cond
((null? lst)
(reverse acc))
((and (list? lst-interm) (not (null? lst-interm)))
(flat-do acc (car lst-interm) (append (cdr lst-interm) lst)))
((not (list? lst-interm))
(flat-do (cons lst-interm acc) empty lst))
((list? (car lst))
(flat-do acc (car lst) (cdr lst)))
(else
(flat-do (cons (car lst) acc) empty (cdr lst)))))
(flat-do empty empty a-list))
(flatten-iter (list 1 (list 2 (list 3 4 (list 5 empty 6))) 7 8))
=> (1 2 3 4 5 6 7 8)
尾部重现函数要求它们永远不会返回,因此不能使用堆栈来存储程序的状态。相反,您可以使用函数参数在函数调用之间传递状态。因此,我们需要确定如何维持这种状态。因为我们函数的结果是list?
,所以有必要增加一个空的列表;为此,我们使用了acc
。您可以在上面的else
分支中看到它是如何工作的。但是我们应该能够处理嵌套列表。在深入研究的同时,我们应该保留嵌套列表的其余元素,以便进一步处理。示例列表:(列表1(列表2 3)4 5)
在(列表2 3)
之前,我们已经在累加器中添加了1
。因为我们不能使用堆栈,所以我们需要其他地方来存储列表的其余元素。这个地方是lst
参数,它包含要展平的原始列表的元素。我们可以只将lst
附加到其余元素(cdr(列表2-3))
,这些元素是(列表3)
,然后继续使用我们在展平时偶然发现的列表头,即。E(汽车(清单2-3)),它只是2
。现在,(and(list?lst interm)(not(null?lst interm))
成功了,因为平面do
被称为:
(flat-do (list 1) (list 2 3) (list 4 5))
条件会触发此代码:
(flat-do (list 1) (car (list 2 3)) (append (cdr (list 2 3)) (list 4 5)))
flat do
又是这样叫的:(flat do(列表1)2(列表3 4 5))
条件(not(list?2))
现在成功,并计算代码(flat do(cons 2 1)empty(list 3 4 5))
其余处理通过else
分支完成,直到lst
为null?
且反向
在acc
上执行。函数然后返回反向累加器。希望我能够感谢您的快速响应,Yasir。读完后,我确实明白了它在做什么(这很重要),但如果你能告诉我你遵循的思考过程,我将不胜感激。对不起,我要求太多了!非常感谢到目前为止的帮助。我现在要去吃比萨饼了。如果你不介意的话,让我稍后再详细解释:-)Buen provecho:(享受你的晚餐)当你在等Yasir吃完他的比萨饼时:有一种叫做“延续传递样式”(CPS)的通用技术,它可以转换任何代码片段,以便所有调用都处于尾部位置。Matt最近可能有一篇关于CPS转型的博客文章,你可能想看看。Mamsaac:我更新了答案。我同意@John,CPS是一种很好的技术,值得研究。