i'm working through SICP Chapter 1 "1.3 Formulating Abstractions with Higher-Order Procedures"
the part i'm (currently) having trouble with is where the procedural template (shown below) is transformed into an actual procedure (shown below that) by having its 'slots' turned into formal parameters. What I don't get is where the hell they get the next b at the end of the transformed procedure (just before the closing brackets)?
Surely its just b as in the template?
Anyway, this is the template...
(define (<name> a b)
(if (> a b)
0
(+ (<term> a)
(<name> (<next> a) b))))
And this is the procedure once the parameter slots have been filled in
(define (sum term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))
any illumination much appreciated
The key insight to understand here is that in Scheme we can pass functions as parameters to another function as easily as we would pass, say, numbers. Be aware that the template is incomplete, it should be:
(define (<name> <term> a <next> b)
(if (> a b)
0
(+ (<term> a)
(<name> <term> (<next> a) <next> b))))
The transformation from template to actual procedure is straightforward:
<name>
is the placeholder for the name of the procedure, which happens to be sum
<term>
is the placeholder for the procedure that is applied over each term in the series, in the actual procedure it's also called term
but it could have any other name - for instance, identity
would be an useful procedure to pass along<next>
is the placeholder for a procedure that calculates the next element in the series, for instance it could be as simple as passing along add1
, but the authors chose to also call it next
The next b
part at the end of the actual procedure is just providing the next
(a function) and b
(a number) parameters to the recursive call of the function, this is what's getting passed in the last line:
(sum term (next a) next b)
^ ^ ^ ^ ^
function call "term" function next number "next" function upper limit
Also notice that (next a)
is actually applying the next
procedure to the a
parameter, and passing along to the recursion the result of that application - in fact, this is the only value that changes between calls, and it's effectively advancing the recursion up until the point when (> a b)
becomes false. That's different from what's happening in the second-to-last parameter, where we are passing next
, the function itself and not the result of applying it. As an example, here's how you'd call the sum
procedure to add all the numbers between 1
and 10
:
(sum identity 1 add1 10) ; <term> is `identity` and <next> is `add1`
=> 55