;; Caltech CS1 Fall 2007
;; Scheme code used in Lecture 7 (10/22/07)
;; mvanier@cs.caltech.edu
;;
;; [clarify function application]
;;
;; To evaluate a function call:
;; 1. Evaluate the arguments
;; 2. Apply the function
;;
;; To Apply a function 
;; 1. Replace the function argument variable with 
;;      the value given in the call everywhere it occurs
;;      - Deep substitution
;;      - Except:
;;          Do *not* substitute for the variable inside a 
;;          lambda expression that uses the same variable 
;;          as its argument.
;; 2. Evaluate the resulting expression
;;

;; Examples:
;; motivation
(define add1 (lambda (x) (+ x 1))
(define add2 (lambda (x) (+ x 2))
(define add3 (lambda (x) (+ x 3))
(define add4 (lambda (x) (+ x 4))
(define add5 (lambda (x) (+ x 5))

;; higher-level function, avoid repetition:
(define (make-addn n)
  (lambda (x) (+ x n)))

;; equivalent def 
(define make-addn   
  (lambda (n) 
    (lambda (x) (+ x n))))

;; uses
(define add2 (make-addn 2))
(define add3 (make-addn 3))

;; substitution example with lambda shielding:
(define weird-protection-example
  (lambda (n)
    (lambda (n) (+ n n))))
(define foo (weird-protection-example 3))
;; Should bind foo to (lambda (n) (+ n n))
;; Not (lambda (n) (+ 3 3))
;; Certainly not (lambda (3) (+ 3 3)) !

;; another example
(define select-op
  (lambda (b)
    (if b
        (lambda (a b) (and a b))
        (lambda (a b) (or a b)))))

;;  Summation, from last time
(define (sum f low high)
  (if (> low high) 0
      (+ (f low) 
         (sum f (+ low 1) high))))

;; Abstract sum around high:
(define (make-sum f low)
  (lambda (high)
    (sum f low high))) ;; sum defined above
;; use
(define sum-squares-to-n (make-sum (lambda (x) (* x x)) 0))

;; function that returns a function that returns 
;;  a function that returns a number
(define multi-stage-add
  (lambda (a) ;; function
    (lambda (b) ;; returns a function
      (lambda (c) ;; returns a function
        (+ a b c))))) ;; returns a number

;; use
(define add-3-b-c (multi-stage-add 3))
(define add-3-4-c (make-add-3-b-c 4))
(add-3-4-c 5)
