SUMMING A COLLECTION OF NUMBERS

Problem: Given a collection of numbers, determine their sum. Let's assume that the numbers are given in the form of a list.

An ex-Pascal or ex-C programmer new to Scheme is likely to draft something like this:

(define sum
  (lambda (numbers)
    (define total 0)
    (while (not (null? numbers))
      (begin
        (set! total (+ total (car numbers)))
        (set! numbers (cdr numbers))))
    total))
and then find herself stymied by the absence of a while-loop in Scheme. Eventually, after carefully working out the syntax and semantics of do-expressions, she arrives at the following code, which is about as close as Scheme comes to the Pascal algorithm:
(define sum
  (lambda (numbers)
    (do ((total 0)
         (rest numbers (cdr rest)))
        ((null? rest) total)
      (set! total (+ total (car rest))))))
This is correct and reasonably efficient, but it still bears discernible traces of the programmer's struggle against the language.

A student who is learning Scheme as her first programming language might think first of recursion:

(define sum
  (lambda (numbers)
    (if (null? numbers)
        0
        (+ (car numbers) (sum (cdr numbers))))))
and then realize that one can gain efficiency by making the procedure tail-recursive:
(define sum
  (lambda (numbers)
    (let loop ((rest numbers)
               (total 0))
      (if (null? rest)
          0
          (loop (cdr rest) (+ total (car rest)))))))
The old hand at Scheme, however, will be familiar with the functional-programming trick that produces the most concise and most efficient version:
(define sum
  (lambda (numbers)
    (apply + numbers)))


This document is available on the World Wide Web as

http://www.math.grin.edu/~stone/events/scheme-workshop/summation.html


created July 9, 1995
last revised June 21, 1996

John David Stone (stone@math.grin.edu)