这个scheme函数好像是尾递归的,所以为什么会出现栈溢出
This scheme function seems to be tail recursive, so why am I getting a stack overflow
我最近几年来一直在胡思乱想 scheme。
我正在使用 repl.it 来玩一下。
我写了这个基本函数来获取列表和 return 双向链表。列表的每个单元格都是一对,其 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 '() '())))
我标记了我认为是仅有的两个递归调用。根据 R6RS,它们在我看来都处于尾部上下文中,但调用该函数会导致堆栈溢出。关于为什么的任何想法?
是的。您的代码确实是尾递归的。当我在 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)
我最近几年来一直在胡思乱想 scheme。 我正在使用 repl.it 来玩一下。 我写了这个基本函数来获取列表和 return 双向链表。列表的每个单元格都是一对,其 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 '() '())))
我标记了我认为是仅有的两个递归调用。根据 R6RS,它们在我看来都处于尾部上下文中,但调用该函数会导致堆栈溢出。关于为什么的任何想法?
是的。您的代码确实是尾递归的。当我在 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)