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