SICP Study

4.2 Variations on a Scheme—Lazy Evaluation

4.2.1 Normal Order and Applicative Order

(define (try a b) (if = a 0) 1 b)

4.2.2 An Interpreter with Lazy Evaluation

Highlights

The word thunk was invented by an informal working group that was discussing the implementation of call-by-name in Algol 60. They observed that most of the analysis of (“thinking about”) the expression could be done at compile time; thus, at run time, the expression would already have been “thunk” about. (Footnote 4.34)

Modifying the evaluator

((application? exp)
 (apply (actual-value (operator exp) env)
        (operands exp)
        env))
(define (actual-value exp env) (force-it (eval exp env)))
(define (apply procedure arguments env)
  (cond ((primitive-procedure? procedure)
         (apply-primitive-procedure
          procedure
          (list-of-arg-values arguments env)))  ; changed
        ((compound-procedure? procedure)
         (eval-sequence
          (procedure-body procedure)
          (extend-environment
           (procedure-parameters procedure)
           (list-of-delayed-args arguments env) ; changed
           (procedure-environment procedure))))
        (else (error "Unknown procedure type: APPLY" procedure))))
(define (eval-if exp env)
  (if (true? (actual-value (if-predicate exp) env))
      (eval (if-consequent exp) env)
      (eval (if-alternative exp) env)))

Representing thunks

(define (force-it obj)
  (if (thunk? obj)
      (actual-value (thunk-exp obj) (thunk-env obj))
      obj))
(define (delay-it exp env) (list 'thunk exp env))
(define (thunk? obj) (tagged-list? obj 'thunk))
(define (thunk-exp thunk) (cadr thunk))
(define (thunk-env thunk) (caddr thunk))

4.2.3 Streams as Lazy Lists

(define ones (cons 1 ones))
(define (scale-list items factor) (map (lambda (x) (* x factor)) items))