(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>.
我是新来的,所以请帮忙。谢谢!
答案 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)))))))
你应该确保你理解所有这些解决方案,因为它们表达了各种各样的方案惯用语,你会发现它们对你未来的编程非常有用。