Procedures that can manipulate other procedures are called as high order procedure.
The main reason that this is useful is that instead of being able to just operate on primitives such as multiplication etc, we are able to formulate patterns and ideas that are high level abstractions and use them as operations, this is much more powerful.
One of the things we should demand from a powerful programming language is the ability to build abstrac- tions by assigning names to common paerns and then to work in terms of the abstractions directly. Procedures provide this ability.
For example we look at the 'sum-of-integers', 'sum-cubes' procedures, we can see that they all have the same pattern.
define (⟨name⟩ a b)
(if (> a b)
0
(+ (⟨term⟩ a)
(⟨name⟩ (⟨next⟩ a) b))))
We are able to use this procedure as an abstraction for summation.
Types of ways that one cane manipulate:
Passing procedures as arguments
Procedures as return values
Procedures with no name.
(lambda (x) (* x x))
(define square
(lambda(x)(* x x)))
(define (square x) (* x x))
In the above code, all the sqaure procedures are the same, one thing to remember in lisp is that all are just expressions that can be passed into other expressions.
(let ((⟨var1 ⟩ ⟨exp1 ⟩)
(⟨var2 ⟩ ⟨exp2 ⟩)
...
(⟨varn ⟩ ⟨expn ⟩))
⟨body⟩)
This is a set of examples of how abstraction is used to express generals methods of computation.
Fixed point
Half-interval method
(define (average-damp f)
(lambda (x) (average x (f x))))
((average-damp square) 10) ;; 55
The procedure takes a procedure as a argument and returns another procedure.
One should be able to identify underlying patterns and build abstractions on top of them and generalize them, but its always not necessary to always build abstraction.
They may be named by variables.
They may be passed as arguments to procedures.
They may be returned as the results of procedures.
They may be included in data structures