Recursion 递归与尾部递归
我对函数式编程非常陌生,尤其是下面使用的Scheme。我试图使下面的函数是递归的,尾部递归。 基本上,该函数所做的是对两个字符串进行对齐。当给定两个字符串作为输入时,它会比较每个字符的“列”,并根据在下面代码中的函数调用的名为scorer的函数中实现的计分方案,为该对齐累积分数 我有一种想法,就是使用一个helper函数来累积分数,但我不太确定如何做到这一点,因此,我应该如何使尾部下面的函数递归Recursion 递归与尾部递归,recursion,functional-programming,tail,Recursion,Functional Programming,Tail,我对函数式编程非常陌生,尤其是下面使用的Scheme。我试图使下面的函数是递归的,尾部递归。 基本上,该函数所做的是对两个字符串进行对齐。当给定两个字符串作为输入时,它会比较每个字符的“列”,并根据在下面代码中的函数调用的名为scorer的函数中实现的计分方案,为该对齐累积分数 我有一种想法,就是使用一个helper函数来累积分数,但我不太确定如何做到这一点,因此,我应该如何使尾部下面的函数递归 (define (alignment-score string_one string_two)
(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)
)
下面是使用累加器时的情况:
(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开始。我们还有一个索引
(也从0开始),它跟踪要获取的字符串中的哪个位置。当我们到达任意一个字符串的末尾时,基本情况是返回到目前为止累积的分数。只是想用字符列表来替代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)))))
停在那里没有用。由于这现在已经成为列表迭代,我们可以使用更高阶的过程。通常,我们需要一个左折
或左折
,并且是不要求列表长度相同的实现:
; (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)))
如果累加,且顺序无关紧要,请始终选择左折叠,因为它在方案中始终是尾部递归的。非常感谢:)我想我现在掌握了这个概念。你的代码非常有意义。再次感谢:)您可能需要补充的是,fold
的SRFI/1参考实现确实是尾部递归的(请参阅)。@uselpa左fold
始终是。许多实现都提供了自己的SRFI-1,它始终是尾部递归的。map
的性能比参考实现要好得多。为什么要停在fold
?您可以使用SRFI 13中的字符串折叠
,并跳过字符串->列表
步骤@ChrisJester Youngstring fold
不接受多个字符串参数,因此您不能以相同的方式使用它。@Sylvester Quick,提交一份错误报告!(说真的,我可以理解为什么有多个字符串会很麻烦,因为还需要能够选择性地提供开始/结束参数。不过,还是很糟糕。)