如何使用chez方案获取给定列表中所有元素的总和?

时间:2014-03-24 18:28:48

标签: list sum scheme

(define lista (list 1/2 2/3 3/4 4/5 5/6))
(define l (length lista))

(define suma (
lambda() (
    (let s((i 0))
        (if (= l 1)
            (list-ref lista i)
            (   (if(< i (- l 2))
                    (+ (list-ref lista i) (s (+ i 1)))      
                )
            )
        )
    )
)   
)
)

我跑(suma)时出现以下错误:

attempt to apply non-procedure #<void>.

我是新来的,所以请帮忙。谢谢!

2 个答案:

答案 0 :(得分:4)

添加列表中所有元素的最简单方法是使用apply

(apply + lista)
=> 3 11/20

但我想你想从头开始实现这个。你的程序有很多的括号错误,你在列表上迭代的方式(使用list-ref)不是惯用的 - 在Scheme中我们使用递归来遍历列表,而不是索引。修复它需要相当多的工作:

(define suma
  (lambda ()
    (let s ((i 0))
      (if (= i (- l 1))
          (list-ref lista i)
          (+ (list-ref lista i)
             (s (+ i 1)))))))

但是,即使我们使用显式递归来解决这个问题,上面也不是惯用的。更符合Scheme精神的解决方案如下所示,并注意遍历列表的模板:

(define (suma lst)           ; pass the list as a parameter
  (if (null? lst)            ; is the list empty? then
      0                      ; we've reached the base case, return 0
      (+ (car lst)           ; otherwise add the current element
         (suma (cdr lst))))) ; and advance the recursion

或者,我们可以使用tail recursion来编写更有效的解决方案:

(define (suma lst)
  (let s ((lst lst)              ; list to traverse
          (acc 0))               ; accumulated result
    (if (null? lst)              ; if the list is empty
        acc                      ; return the accumulator
        (s (cdr lst)             ; otherwise advance recursion
           (+ (car lst) acc))))) ; and update accumulator

无论哪种方式,我们将输入列表作为参数传递,它按预期工作:

(suma lista)
=> 3 11/20

答案 1 :(得分:2)

最简单的答案,以及经验丰富的Scheme程序员无疑会使用的答案是:

(define (sum xs) (apply + xs))

如果您需要递归解决方案,可以使用:

(define (sum xs) (if (null? xs) 0 (+ (car xs) (sum (cdr xs)))))

对于迭代的尾递归解决方案,您可以使用名为let:

(define (sum xs)
  (let loop ((xs xs) (sum 0))
    (if (null? xs) sum
      (loop (cdr xs) (+ sum (car xs))))))

这是另一个迭代解决方案,使用do:

(define (sum xs)
  (do ((xs xs (cdr xs)) (sum 0 (+ sum (car xs))))
      ((null? xs) sum)))

如果你坚持使用list-ref,这是一个解决方案;它将是这里显示的效率最低的,因为list-ref重复遍历列表:

(define (sum xs)
  (let ((len (length xs)))
    (let loop ((i 0) (sum 0))
      (if (= i len) sum
        (loop (+ i 1) (+ sum (list-ref xs i)))))))

你应该确保你理解所有这些解决方案,因为它们表达了各种各样的方案惯用语,你会发现它们对你未来的编程非常有用。