Functional programming 方案中的尾部递归计数函数
函数应该是尾部递归的,并且从1计数到指定的数字。我想我已经很接近了。以下是我所拥有的:Functional programming 方案中的尾部递归计数函数,functional-programming,scheme,Functional Programming,Scheme,函数应该是尾部递归的,并且从1计数到指定的数字。我想我已经很接近了。以下是我所拥有的: (define (countup l) (if (= 1 l) (list l) (list (countup (- l 1)) l ) ) ) 但是,这显然会返回一个包含嵌套列表的列表。我尝试使用append函数代替第二个列表,但没有成功。有什么指导吗?这里是您的代码的工作版本,它以正确的顺序返回列表(我将l替换为n):
(define (countup l)
(if (= 1 l)
(list l)
(list
(countup (- l 1))
l
)
)
)
但是,这显然会返回一个包含嵌套列表的列表。我尝试使用append函数代替第二个列表,但没有成功。有什么指导吗?这里是您的代码的工作版本,它以正确的顺序返回列表(我将
l
替换为n
):
遗憾的是,这段代码有一个问题:它不是尾部递归的。原因是对countup
的递归调用不在尾部位置。它不在尾部位置,因为我正在追加(countup(-l 1))
,所以尾部调用是append
(或者list
,当n=1
)而不是countup
。这意味着这段代码是一个正常的递归函数,但却是一个尾部递归函数
查看维基百科上的这篇文章,可以找到一个更好的例子,说明为什么它不是尾部递归
要使其尾部递归,您需要一个累加器负责累加计数的值。这样,您就可以将递归函数调用置于尾部位置。看看我给你的链接有什么不同
如果您需要更多详细信息,请随时回复。这里有一个不正确的解决方案:
(define (countup n)
(define (help i)
(if (<= i n)
(cons i (help (+ i 1)))
'()))
(help 1))
注意事项:
- 此解决方案更好,因为可以立即评估对
的调用,因此此函数是尾部递归优化(TCO)的候选函数,在这种情况下,堆栈空间不会成为问题cons
向后递归数字,从而避免了使用help
,这可能非常昂贵append
(countup 5) => (list 1 2 3 4 5)
这里有一个提示-在尾部递归函数中,尾部位置的调用应该是对自身的(除非是边缘情况)
由于countup不接受数字列表,因此需要一个累加器函数,该函数接受数字和列表,并返回列表
以下是一个模板:
;; countup : number -> (listof number)
(define (countup l)
;; countup-acc : number, (listof number) -> (listof number)
(define (countup-acc c ls)
(if ...
...
(countup-acc ... ...)))
(countup-acc l null))
在countup acc的内部调用中,您需要更改在edge case中检查的参数,以使其更接近该edge case,您需要更改另一个参数,使其更接近最终要返回的值。您应该使用辅助函数来实现此问题的尾部递归解决方案(“循环”函数),并使用额外的参数来累积答案。大概是这样的:
(define (countup n)
(loop n '()))
(define (loop i acc)
(if (zero? i)
acc
(loop (sub1 i) (cons i acc))))
或者,您可以使用命名let。无论哪种方式,解决方案都是尾部递归的,并且使用一个参数来累积值,请注意,递归向后推进,从n
开始,然后倒计时到0
,依次考虑列表开头的每个值:
(define (countup n)
(let loop ((i n)
(acc '()))
(if (zero? i)
acc
(loop (sub1 i) (cons i acc)))))
它应该返回什么?n个元素的列表,按升序从1到n,其中n是输入?是的,没错。按从1到指定数字的升序列出n个元素。对不起,我不太清楚。这不是尾部复发。该函数中的最后一个调用转到“list”而不是“countup”。
(define (countup n)
(loop n '()))
(define (loop i acc)
(if (zero? i)
acc
(loop (sub1 i) (cons i acc))))
(define (countup n)
(let loop ((i n)
(acc '()))
(if (zero? i)
acc
(loop (sub1 i) (cons i acc)))))