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?
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.