Reputation: 599
In section 1.3 of SICP, we are abstracting the summation process by introducing two procedures as arguments for the procedure.
(define (sum term a next b)
(if (> a b) 0
(+ (term a) (sum term (next a) next b))))
Why can't we write the same procedure like this:
(define (identity a ) a)
(define (next a) (+ a 1)
(define (sum a b)
(if (> a b) 0
(+ (identity a) (sum (next a) b))))
I am not able to understand the reason for passing procedures as arguments in this particular example.
Is there any special reason for that? Or is it just for the purpose of demonstrating the concept?
Is there a better example?
Upvotes: 2
Views: 167
Reputation: 702
It just like you say it just summation notation. If you learn basic math you might need to calculate many series.
We can think in many point.
(define (1/1+1/2+1/3+...+1/k k) (summation / 1 add1 k))
Then we only need to translate to sum of 1/i form i=1 to i=k (in here is i≦k) just like we learn it in math course.+
function (inside sum
) to add-vector
and add if-else
to check input is number or vector. We can design something like my-inf
so we can use another way to calculate 1+2+3+...+inf
.sqrt
we all agree this abstraction is important because we have many algorithm to calculate sqrt
.#lang racket
(define (sum term a next b)
(if (> a b) 0
(+ (term a) (sum term (next a) next b))))
(define (1+2+...+k k)
(sum identity 1 add1 k))
(define (0^2+1^2+2^2+...+k^2 k)
(sum sqr 0 add1 k))
(define (1+3+5+...+k k)
(sum (λ (n) (- (* 2 n) 1)) 1 add1 k))
(define (1/1+1/2+1/3+...+1/k k)
(sum / 1 add1 k))
(define (1/1^2+1/2^2+1/3^2+...+1/k^2 k)
(sum (λ (n) (/ (sqr n))) 1 add1 k))
; sqr(0)+sqr(2)+sqr(4)+sqr(6)
(sum sqr 0 (λ (a) (+ a 2)) 7) ; 56
;;; TEST
(0^2+1^2+2^2+...+k^2 3) ; 14
(1+2+...+k 100) ; 5050
(1+3+5+...+k 5) ; 1+3+5+7+9=25
(1/1+1/2+1/3+...+1/k 5) ; (+ 1/1 1/2 1/3 1/4 1/5) = 2 + 17/60
(1/1^2+1/2^2+1/3^2+...+1/k^2 3) ; (+ 1 1/4 1/9) = 1 + 13/36
Upvotes: 2
Reputation: 15803
If you want to compute
f(a0) + f(a0+r) + f(a0+2r) + ...
you cannot use your second form but use the form from SICP. Scheme helps you implementing in a nice way the abstract concept of ∑.
Upvotes: 1
Reputation: 236112
The reason for passing procedures as arguments is that in this way you can parameterize your procedure, changing its behavior. Surely, in the original version you can simply add all the numbers, the same as in the second version:
(define (sum term a next b)
(if (> a b)
0
(+ (term a) (sum term (next a) next b))))
(define (identity a) a)
(define (plus1 a) (+ 1 a))
(sum identity 1 plus1 10)
=> 55
But now you also have the flexibility to calculate other series, without changing the original code - you just have to pass different procedures to get different results. Say, you want to calculate the sum of the squares:
(define (square a) (* a a))
(sum square 1 plus1 10)
=> 385
Or you want to calculate the sum, but skipping numbers:
(define (plus2 a) (+ 2 a))
(sum identity 1 plus2 10)
=> 25
That is the power of higher order procedures: customizability and extensibility with no changes to the base code. And because procedures can be written in such a way that they're composable and reusable, you have a very flexible way to think about computation, without having to write boilerplate code over and over again.
Upvotes: 3