Recursion 这个scheme函数似乎是尾部递归的,那么为什么会出现堆栈溢出呢

Recursion 这个scheme函数似乎是尾部递归的,那么为什么会出现堆栈溢出呢,recursion,scheme,tail-recursion,Recursion,Scheme,Tail Recursion,我最近几年来第一次在这个计划上胡闹。 我正在使用repl.it玩一玩。 我编写了这个基本函数来获取一个列表并返回一个双链接列表。列表的每个单元格都是一对,其car是列表元素,其cdr与car中的前一个元素和cdr中的下一个元素成对。第一个和最后一个元素的前一项和下一项分别为null。我编写的函数是尾部递归的。我现在知道scheme实际上有循环语法,但我在写它时的印象是,在scheme中循环的唯一方法是使用尾部递归。我的代码如下: (define (dbllink li) (letrec

我最近几年来第一次在这个计划上胡闹。 我正在使用repl.it玩一玩。 我编写了这个基本函数来获取一个列表并返回一个双链接列表。列表的每个单元格都是一对,其car是列表元素,其cdr与car中的前一个元素和cdr中的下一个元素成对。第一个和最后一个元素的前一项和下一项分别为null。我编写的函数是尾部递归的。我现在知道scheme实际上有循环语法,但我在写它时的印象是,在scheme中循环的唯一方法是使用尾部递归。我的代码如下:

(define (dbllink li) 
    (letrec ((step (lambda (lis prev head) 
                           (if (null? lis) 
                               head 
                               (let ((cell (cons (car lis) 
                                                 (cons prev '()))))
                                 (if (null? prev) 
                                     (step (cdr lis);<--recursive call
                                           cell 
                                           cell) 
                                     (begin (set-cdr! (cdr prev)
                                                      cell) 
                                            (step (cdr lis);<--recursive call
                                                  cell 
                                                  head ))))))))
        (step li '() '())))
(定义(dbllink li)
(letrec)(步骤(lambda(lis上封头)
(如果(空?lis)
头
(let)单元(cons)单元(car lis)
(((()))
(如果(空?上一个)

(步骤(cdr lis);是的。您的代码确实是尾部递归的。当我在DrRacket的r6rs中尝试这一点时,我得到了

(dbllink '(1 2 3 4 5)) 
; ==> #0={1 () . #1={2 #0# . #2={3 #1# . #3={4 #2# 5 #3#}}}}
这形成了一个循环结构。我想也许BiwaScheme试图打印它,但你不能用尾部递归打印列表结构,它不会检查循环列表,所以你最终会出现堆栈溢出

您可以通过指定结果来验证这一点,这样它就不会打印结果

(define test (dbllink '(1 2 3 4 5))   ; ==> #void
(car test) ; ==> 1
test ; ("too much recursion" in Biwa)

嗯……它不应该是圆形的。也就是说,第一个元素和最后一个元素的下一个和上一个“字段”应该是空的。或者你的意思是,小圆圈是由连续的元素相互指向形成的?