Scheme 理解尾部递归向量

Scheme 理解尾部递归向量,scheme,tail-recursion,Scheme,Tail Recursion,我有一个尾部递归函数,它将向量转换为列表。我理解每一行,但有几个问题: 首先,在代码中,代码cons((向量ref v i)r)(-i1)是什么意思?(标记为“Q1”)我知道它接受向量v的I第个元素,并将其与I-1连接,但为什么必须是I-1?为什么不使用i+1?e、 g.如果向量v长度总计为5,则元素编号5与编号4连接。我知道它正在制作向量列表,但为什么要使用I-1(减少)?谁能给我解释一下吗 (define vector->list:rec (lambda (v) (letrec

我有一个尾部递归函数,它将向量转换为列表。我理解每一行,但有几个问题:

首先,在代码中,代码
cons((向量ref v i)r)(-i1)
是什么意思?(标记为“Q1”)我知道它接受向量
v
I
第个元素,并将其与
I-1
连接,但为什么必须是
I-1
?为什么不使用
i+1
?e、 g.如果向量v长度总计为5,则元素编号5与编号4连接。我知道它正在制作向量列表,但为什么要使用
I-1
(减少)?谁能给我解释一下吗

(define vector->list:rec
 (lambda (v)
   (letrec ((helper
          (lambda (vec r i)
            (if (< i 0) 
                r
                (helper vec (cons (vector-ref v i) r) (- i 1))  ;; Q1
                ))))
     (if (> (vector-length v) 0)  ;; line 9
      (helper v (cons (vector-ref v (- (vector-length v) 1)) '()) (- (vector-length v) 2))
      '()))))
(定义向量->列表:rec
(五)
(letrec)((helper)
(lambda(vec r i)
(如果((向量长度v)0);;第9行
(辅助向量v(cons(向量参考向量v(-(向量长度v)1))'()((向量长度v)2))
'()))))

每次调用
i
都会减少的原因是
i
用于确定何时到达向量的末尾。其思想是,当我们最初调用
helper
函数时,我们将
i
设置为向量的长度(减2),然后在每次递归调用中,将
i
减少1,直到它变为小于0,此时我们知道已经遍历了整个向量

我相信,引起您混淆的问题是您错误地解析了
cons
调用-计算括号表明调用实际上是
(cons(vector ref v I)r)
-
(.I 1)
只是
助手的第三个参数


最后,在第9行检查向量的长度是否大于0的想法是,如果向量的长度为0,我们只想返回一个空列表
'()
;如果我们没有做这个检查,那么调用
(vector ref v(-(vector length v)1))
将变成
(vector ref v-1)
,如果我们输入一个空向量,这显然会失败。我不确定你所说的“总长度检查”是什么意思,但是
(向量长度v)
确实返回了
v
的整个长度明智地使用print语句来理解递归函数的工作原理是非常有帮助的。我补充说

      (print r)
就在下面

      (lambda (vec r i)
我运行命令:

(vector->list:rec (vector 1 4 6 8 9 10))
以下是输出:

(10) (9 10) (8 9 10) (6 8 9 10) (4 6 8 9 10) (1 4 6 8 9 10) => (1 4 6 8 9 10) 通过使用

      (list (vector-ref v (- (vector-length v) 1)))
对第一季度的回答

线路

            (helper vec (cons (vector-ref v i) r) (- i 1))  ;; Q1
 (if (> (vector-length v) 0)  ;; line 9
(在方案中,
cons
es)将向量的
i
-th元素预先添加到包含向量的
i+1
-th及以上项的列表中

在我运行的示例中,当
I
3
时,
r
(9 10)

如果我理解正确的话,这与你所认为的相反

此函数从
i
的最高有效值递归,并在每次递归调用中递减。这就是
(-i1)
作为上述调用
helper
的最后一个参数

回答“另外,总长度检查在哪里?”

线路

            (helper vec (cons (vector-ref v i) r) (- i 1))  ;; Q1
 (if (> (vector-length v) 0)  ;; line 9
检查输入的总长度是否大于0。只有这样,它才能通过调用
helper
来解决问题。否则,它只返回一个空列表


希望这有点道理。

@user1915570是的,我写这篇文章时是指-2。原因是我们首先去掉
(vector ref v(-(vector length v)1)中的最后一个元素-
,即-1-,然后在我们的检查中使用
。如果它是
(我建议您在第二个问题中使用尾部递归。谢谢。我现在明白了。我在另一个回答中又添加了一个问题,但我不明白为什么我们需要第10行。这是因为它不包括在If例程中。这只包括内部循环(?)除了最后一个元素(-1)和(-2)=>因为我们没有包括0。但是在这里第10行,它是向量元素-2(=最后的第二个元素)。这意味着第10行将最后一个元素与第二个最后一个元素连接起来。为什么我们需要它?@user1915570第10行需要启动整个过程。第7行中对
helper
的调用允许程序循环,但为了首先启动循环,我们需要调用第10行中的
helper
。我可以把它放在哪里(打印r)?行的正下方
(lambda(vec r i)
当我使用print时,它显示这个==>print:undefined;无法引用未定义的标识符。我很惊讶。你正在使用的Scheme解释器似乎没有定义
print
。这很奇怪。我也是。反正使用Racket。我刚开始使用它。对Scheme或Racket都不太了解