sicp-4-2-1

Posted on 2015-03-11 19:20:01 +0900 in SICP Lisp

4.25

(define (unless condition usual-value exceptional-value)
  (if condition exceptional-value usual-value))

(define (factorial n)
  (unless (= n 1)
    (* n (factorial (- n 1)))
    1))

In applicative-order, factorial will enter an infinite loop, as the exceptional-value is evaluated regardless the condition.

While in normal-order, the condition is judged before exceptional-value is evaluated.

4.26

(define (unless? exp) (tagged-list? exp 'unless))
(define (unless-clauses exp) (cdr exp))
(define (unless-condition clauses) (car clauses))
(define (unless-usual-value clauses) (cadr clauses))
(define (unless-exceptional-value clauses) (caddr clauses))
(define (unless->if exp)
  (expand-unless-clauses (unless-clauses exp)))
(define (expand-unless-clauses clauses)
  (make-if (unless-condition clauses)
           (unless-exceptional-value clauses)
           (unless-usual-value clauses)))

It would fail if unless is passed as parameter, as there is no such procedure.

4.27

(define count 0)
(define (id x)
  (set! count (+ count 1))
  x)

(define w (id (id 10)))
;;; L-Eval input:
count
;;; L-Eval value:
1
;;; L-Eval input:
w
;;; L-Eval value:
10
;;; L-Eval input:
count
;;; L-Eval value:
2

(define w (id (id 10))) will cause the outer id being force, (id 10) is not evaluated and being returned as a thunk.

The evaluation of w forces the inner id being forced.

4.28

I think it would cause trouble if the operator is a thunk instead of actual procedure. In order to make the operator be a thunk, the easiest way is to pass the procedure as a parameter. such as:

(define (g x) (+ x 1))
(define (f g x) (g x))
(f g 10)

4.29

;;; L-Eval input:
(square (id 10))
;;; L-Eval value:
100
;;; L-Eval input:
count
;;; L-Eval value:
1 ; with memorization, (id 10) is called once.
2 ; without memorization, (id 10) is called twice

To test the efficiency, simillar to the 4.24 problem.

(eval '(define (factorial n)
  (if (= n 1)
      1
      (* (factorial (- n 1)) n))) the-global-environment)

(let ((t0 0) (t1 0))
  (define (loop i n)
    (eval '(factorial 1234) the-global-environment)
    (if (< i n)
      (loop (+ i 1) n)))
  (set! t0 (runtime))
  (loop 0 1)
  (set! t1 (runtime))
  (- t1 t0))

;9.864471 second without memorization
;0.027408 second with memorization

4.30

  1. display is a primitive function, so Ben is right.
  2. with original version, (p1 1) = (1,2) and (p2 1) = 1 while in Cy’s version, both of them would be (1, 2).
(define (p2 x)
  (define (p e)
    e
    x)
  (p (set! x (cons x '(2)))))

(set! x (cons x '(2))) is passed in as a thunk parameter e of the internal p procedure in the original version and is not forced as it is not passed to a primitive procedure.

  1. Obviously.
  2. I prefer the text’s. As lazy evalution is better not involved with side effects.
----------------------------------- 本文内容遵从CC版权协议转载请注明出自kamelzcs -----------------------------------
«  | sicp-4-1-6-4-1-7 »

Hide Comments

comments powered by Disqus