Recursion 格式中的递归函数

Recursion 格式中的递归函数,recursion,scheme,racket,Recursion,Scheme,Racket,我需要做一个递归函数,它接受一个对象和一个向量,并返回一个在我的对象参数之前的所有对象的列表 我是这样使用迭代的: (define (precedes obj vec) (do ((i 1 (+ i 1)) (list '() (if (eqv? obj (vector-ref vec i)) (cons(vector-ref vec (- i 1)) list) list))) ((= i (vector-length v

我需要做一个递归函数,它接受一个对象和一个向量,并返回一个在我的对象参数之前的所有对象的列表

我是这样使用迭代的:

(define (precedes obj vec)
  (do ((i 1 (+ i 1))
      (list '() (if (eqv? obj (vector-ref vec i))
            (cons(vector-ref vec (- i 1)) list)
            list)))
    ((= i (vector-length vec)) list))
)
但是我在试图找出如何使用递归做同样的事情时遇到了很多麻烦。我很困惑,当我递归调用时,如何通过向量不断递增。到目前为止,我只知道:

(define (precedes2 obj vec)
  (define list '())
  (if (eqv? obj (vector-ref vec i))
      (cons(vector-ref vec(- i 1)) list)
      list)))

我想我会使用我以前在if语句中使用的相同逻辑,但我不确定现在如何使用更新的向量调用相同的函数。任何帮助都会很好。

您正处于从迭代实现转向递归实现的有趣位置;通常人们往另一个方向走。幸运的是,从do循环到递归非常容易。通常,do循环可以重写如下:

(do ((i i-init i-step)
     (j j-init j-step)
     ...)
    (test result)
  body)
变成

(define f (i j ...)
  (cond
    (test result)
    (else body (f i-step j-step ...))))

(f i-init j-init ...)
该翻译通常使用命名let编写,不过:

(let f ((i i-init)
        (j j-init)
        ...)
  (cond
    (test result)
    (else body (f i-step j-step ...))))
所以(我还没有测试代码)您的原始函数

(define (precedes obj vec)
  (do ((i 1 (+ i 1))
      (list '() (if (eqv? obj (vector-ref vec i))
            (cons(vector-ref vec (- i 1)) list)
            list)))
    ((= i (vector-length vec)) list))
)
会变成

(define (precedes obj vec)
  (let loop ((i 1)
             (list '()))
    (cond
      ((= i (vector-length vec)) list)
      (else (loop (+ i 1)
                  (if (eqv? obj (vector-ref vec i))
                      (cons (vector-ref vec (- i 1)) list)
                      list))))))

感谢您提供有关逻辑的详细信息。真的帮助我更好地理解这门语言。就像2周前刚开始用Scheme编码一样。@Ganda正如我在开始时提到的,这是一个相当有趣的案例,因为编写递归版本通常比较容易,然后(在公共Lisp中,不一定要消除尾部调用)使用do编写版本。我认为,朝另一个方向走不太常见。