Scheme 从递归到迭代的每个过程,反之亦然?

Scheme 从递归到迭代的每个过程,反之亦然?,scheme,lisp,racket,Scheme,Lisp,Racket,你能把每一个递归过程和递归过程从递归(甚至是树递归)转换成迭代,反之亦然(在Scheme中)? 通过改变代码的编写方式?当然可以。 递归函数总是有一个中断条件。 有时中断条件是关于一个列表,该列表已用完,因此从递归调用到下一个递归调用变为空。 在这种情况下,您可以通过列表上的for循环来处理它。 有时中断条件是关于某个数字的减少或其他情况-然后可以使用while循环来测试中断条件。您必须区分递归函数/过程和递归过程。想象一下走在一棵二叉树上。这当然是一个递归过程,因为无论您如何实现它,您都需要回

你能把每一个递归过程和递归过程从递归(甚至是树递归)转换成迭代,反之亦然(在Scheme中)? 通过改变代码的编写方式?

当然可以。 递归函数总是有一个中断条件。 有时中断条件是关于一个列表,该列表已用完,因此从递归调用到下一个递归调用变为空。 在这种情况下,您可以通过列表上的for循环来处理它。
有时中断条件是关于某个数字的减少或其他情况-然后可以使用while循环来测试中断条件。

您必须区分递归函数/过程和递归过程。想象一下走在一棵二叉树上。这当然是一个递归过程,因为无论您如何实现它,您都需要回溯,因此,如果您使它迭代,您将有某种数据结构替换递归解决方案中使用的系统堆栈

使用相同的算法,您无法将递归过程转换为迭代过程。这是不可能的

然而,有些算法可能会被做其他事情的其他算法所取代。斐波那契过程就是一个很好的例子。这是一个树漫游版本:

(define (fib-rec n)
  (if (< n 2)
      n
      (+ (fib-rec (- n 1)) 
         (fib-rec (- n 2)))))
这些算法不同。
fib rec
的递归到迭代转换如下:

(define (fib n)
  (let loop ((jobs '(fib)) (args (list n)))
    (cond ((null? jobs)
           (car args))
          ((eq? (car jobs) 'swap)
           (loop (cdr jobs)
                 (list* (cadr args) (car args) (cddr args))))
          ((eq? (car jobs) 'add)
           (loop (cdr jobs)
                 (cons (+ (car args)
                          (cadr args))
                       (cddr args))))
          ((< (car args) 2) 
           (loop (cdr jobs) args))
          (else 
           (loop (list* 'fib 'swap 'fib 'add (cdr jobs))
                 (list* (- (car args) 2) (- (car args) 1) (cdr args)))))))
(定义(fib n)
(let循环((作业(fib))(参数(列表n)))
(条件((空?作业)
(汽车args))
((eq?(汽车作业)交换)
(循环(cdr作业)
(列表*(cadr参数)(car参数)(cddr参数)))
((eq?(汽车作业)添加)
(循环(cdr作业)
(cons(+)(汽车参数)
(cadr args))
(cddr args)))
(<(汽车参数)2)
(循环(cdr作业)参数)
(其他
(循环(列表*'fib'交换'fib'添加(cdr作业))
(列表*((车辆参数)2)((车辆参数)1)(cdr参数(()()())))
这与
fib rec
几乎相同,只是它使用了一个操作列表和一个参数堆栈。这是一个递归过程,但te过程是尾部递归的,因此是迭代的


如果不改变算法,继承的迭代过程就不能转换为递归过程。可以将其视为拥有
fib iter
并将其重写为
fib rec
。此外,由于Scheme除了递归之外并没有原始循环结构,所以所有迭代过程都是通过递归完成的。如果您阅读这些报告,您将看到
do
和其他循环结构是派生语法以及它们变成什么样的递归。

为了清晰起见,请编辑以添加更多单词。重复是可以的,损害清晰度的时尚英语是不可以的。“优雅的事情最好留给裁缝和鞋匠去做”,你知道。但总的来说,如果我猜对了你的要求,是的。查找CP、去功能化、堆上的显式堆栈等。这是否回答了您的问题?非常感谢。从迭代到递归?如果迭代在一个用完的循环或达到某个阈值的计数器上进行,可以设置递归的中断条件,以测试是否达到极限(=极限计数器)或列表末尾
(null lst)
。当通过计数步骤或
(cdr lst)
调用下一个递归调用dlminish/enhance计数器时。如果迭代是while循环,则while中断条件成为递归中断条件。
(define (fib n)
  (let loop ((jobs '(fib)) (args (list n)))
    (cond ((null? jobs)
           (car args))
          ((eq? (car jobs) 'swap)
           (loop (cdr jobs)
                 (list* (cadr args) (car args) (cddr args))))
          ((eq? (car jobs) 'add)
           (loop (cdr jobs)
                 (cons (+ (car args)
                          (cadr args))
                       (cddr args))))
          ((< (car args) 2) 
           (loop (cdr jobs) args))
          (else 
           (loop (list* 'fib 'swap 'fib 'add (cdr jobs))
                 (list* (- (car args) 2) (- (car args) 1) (cdr args)))))))