2014-11-16 88 views
1

我需要制作一个递归函数,该函数需要一个对象和一个向量,并返回在我的对象参数之前的所有对象的列表。Scheme中的递归函数

我把它用迭代这样做的:

(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语句名词前用同样的逻辑,但我不知道现在该怎么用更新的调用同一个函数向量。任何帮助都会很棒。

回答

2

您处于从迭代实现转为递归的有趣位置;通常人们走向另一个方向。幸运的是,从循环到递归非常简单。在一般情况下,一个循环可以被重写如下:

(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 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)))))) 
+0

感谢您对逻辑的细节也是如此。真的帮助我更好地理解语言。仅在2周前开始在Scheme中开始编码。 – Ganda

+0

@Ganda正如我在开头提到的那样,这是一个非常有趣的例子,因为编写递归版本通常更容易,然后(在Common Lisp中,它不一定有尾部调用消除)使用do编写一个版本。我认为,走向另一个方向是不常见的。 –