递归与尾递归

时间:2014-03-31 14:22:56

标签: recursion functional-programming tail

我对函数式编程很陌生,特别是下面使用的Scheme。我试图创建以下递归函数,尾递归。 基本上,函数的作用是对两个字符串的对齐进行评分。当给出两个字符串作为输入时,它会比较每个"列"根据在下面的代码中由函数调用的称为记分器的函数中实现的评分方案,对角色进行积分并累积该对齐的分数。

我有一个想法是使用帮助函数来积累分数,但我不太清楚如何做到这一点,因此我将如何使函数在尾部递归下面?

(define (alignment-score string_one string_two)
  (if (and (not (= (string-length string_one) 0))
           (not (=(string-length string_two) 0)))
      (+ (scorer (string-ref string_one 0)
                 (string-ref string_two 0))
         (alignment-score-not-tail
          (substring string_one 1 (string-length string_one))
          (substring string_two 1 (string-length string_two))
          )
       )
    0)
)

2 个答案:

答案 0 :(得分:1)

只想制作使用字符列表的Chris答案的变体:

(define (alignment-score s1 s2)
  (let loop ((score 0)
             (l1 (string->list s1))
             (l2 (string->list s2)))
    (if (or (null? l1) (null? l2))
        score
        (loop (+ score (scorer (car l1)
                               (car l2)))
              (cdr l1)
              (cdr l2)))))

没有用停在那里。由于现在已成为列表迭代,我们可以使用更高阶的过程。通常我们希望fold-leftfoldlSRFI-1 fold是一种不需要列表长度相同的实现:

; (import (scheme) (only (srfi :1) fold)) ; r7rs    
; (import (rnrs) (only (srfi :1) fold))   ; r6rs    
; (require srfi/1)                        ; racket

(define (alignment-score s1 s2)
  (fold (lambda (a b acc)
          (+ acc (scorer a b)))
        0
        (string->list s1)
        (string->list s2)))

如果你积累并且顺序无关紧要,请选择左侧折叠,因为它总是在Scheme中进行尾递归。

答案 1 :(得分:0)

以下是累加器的外观:

(define (alignment-score s1 s2)
  (define min-length (min (string-length s1) (string-length s2)))
  (let loop ((score 0)
             (index 0))
    (if (= index min-length)
        score
        (loop (+ score (scorer (string-ref s1 index)
                               (string-ref s2 index)))
              (+ index 1)))))

在这种情况下,score是累加器,从0开始。我们还有一个index(也从0开始),它跟踪要捕获的字符串中的哪个位置。当我们到达任一字符串的末尾时,基本情况是返回累积的score到目前为止。

相关问题