Sreekumar R
Sreekumar R

Reputation: 599

Scheme: The purpose of procedure arguments in SICP: 1.3 (Higher Order Procedures)

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

Answers (3)

tjorchrt
tjorchrt

Reputation: 702

It just like you say it just summation notation. If you learn basic math you might need to calculate many series.

  • 1+2+3+...+n
  • 1/n+2/n+3/n+...+n/n
  • 0+2+3+...+n
  • 1^2+2^+3^2+...+n^2
  • f(1)+f(2)+f(3)+...+f(n)
  • f(1)+f(3)+f(5)+...

We can think in many point.

  • abstract : it basic abstract. Summation notation we all learn this in math course. So not strange.
  • modification: In your second version you have to rewrite all code. In first verstion no need. See demo below.
  • understand : If people see code like this: (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.
  • easily test
  • extension : Maybe someday you want extension to vector series. If we want to add vector series: vector-1 + vector-2 + ... + vector-n We only need to change this + 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.
  • new algorithm or speedup : If we talk about 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

alinsoar
alinsoar

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

Óscar López
Óscar López

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

Related Questions