Procedures that return procedures as values are also higher-order procedures.
Recall: If g is a function whose values are acceptable as arguments to f, then the composition of f and g is:
     f(g(x))

Exercise 5.16: Write a procedure that takes two procedures as arguments and returns the procedure that is their composition as a result.
     (define compose	
       (lambda (f g)	
         _______________))

  1. Assume halts? exists.
  2. Then it must return #t or #f for any procedure given it as an argument.
  3. Consider the following procedure:
         (define debunk-halts?
           (lambda ()
             (if (halts? debunk-halts?)
                 (loop-forever)
                 (return-seven))))
    
  4. Now we have both:
    • (halts? debunk-halts) loops forever if debunk-halts halts
    • (halts? debunk-halts) halts with 7 if debunk-halts does not halt
  5. Since 4 is a contradiction, the assumption (1) must be false.
  6. Moral of the story: "mathematically specifiable" and "computable" are different things.
If halts? were to exist, then it could be used to solve problems that mathematicians have not been able to solve. For example:

Q: Are there any odd perfect numbers?

Even if we don't know how to write halts?, we know how it would behave if it were to exist.

Consider:

          (define return-seven 
	     (lambda () 7))

          (define loop-forever
	     (lambda () (loop-forever)))
      
If halts? exists and works as it should, then we know:
	  (halts? return-seven) ⇒ #t

	  (halts? loop-forever) ⇒ #f
      
Q: How could halts? work?
The power of computational processes has led computer scientists to speculate on the following:

Q: Is it possible for any mathematically specified function to be computed by some procedure?

Suppose we want a procedure called arithmetic to take three arguments: an arithmetic operator and two operands:
	  (arithmetic + 3 4)	⇒ 7
	  (arithmetic * 3 4)	⇒ 12
	  (arithmetic remainder 30 4) ⇒ 2
      

Q: Why is arithmetic inconvenient?

Recall a Scheme procedure application:
	  (procedure arg1 arg2 ... argn )
      
All elements of the application, including the procedure itself, are evaluated.
	  (define operate +)
	  (operate 3 4) ⇒ 7
      
Thus a procedure can be given to another procedure as an argument (as data), and then applied to other data (as a program):

Now any of the following will work:

	  (arithmetic + 3 4) → 7
	  (arithmetic * 3 4) → 12
	  (arithmetic remainder 30 4) → 2
	  (arithmetic / 45 17) → 2 11/17
	  (arithmetic expt 3 4) → 81
      
Q: Will only arithmetic procedures work?