sicp-4-1

Posted on 2015-03-06 00:51:11 +0900 in SICP Lisp

4.1

It takes me several minutes to really understand the quanstion. :(

It really only has something to do with the order of the parameter evaluation. To restrict the order, the parameters passed in to cons should be taken out explicitly before being used.

(define (list-of-values-left-right exps env)
  (if (no-operands exps)
    '()
    (let ((left (eval (first-operand exps) env)))
      (cons left
            (list-of-values-left-right (rest-operands exps) env)))))

4.2

A procedure application is any compound expression that is not one of the above expression types. The car of the expression is the operator, and the cdr is the list of operands

The problem lies in the way to determain a procedure which is much too simple.

If it is put at the very beginning, then (define x 3) would be recognized as a procedure, the operator of which is define and the operands are x and 3. But at that time, there is no procedure called define at all.

(define (application? exp) (tagged-list? exp 'call))
(define (operator exp) (cadr exp))
(define (operands exp) (cddr exp))

4.4

((and? exp) (eval-and exp env))
((or? exp) (eval-or exp env))
(define (and? exp)
  (tagged-list? exp 'and))
(define (eval-and exp env)
  (define (eval-and-operands operands)
    (cond ((null? operands) false)
          ((true? (eval (car operands) env))
           (eval-and-operands (cdr operands)))
          (else false)))
  (eval-and-operands (cdr exp)))

(define (or? exp)
  (tagged-list? exp 'or))
(define (eval-or exp env)
  (define (eval-or-operands operands)
    (cond ((null? operands) false)
          ((true? (eval (car operands) env))
           true)
          (else
           (eval-or-operands (cdr operands)))))
  (eval-or-operands (cdr exp)))

;derived version
((and? exp) (eval (and->if exp) env))
((or? exp) (eval (or->if exp) env))

(define (and? exp)
  (tagged-list? exp 'and))
(define (and-clauses exp) (cdr exp))
(define (expand-and-clauses clauses)
  (if (null? clauses)
      'true
      (make-if (car clauses)
               (expand-and-clauses (cdr clauses))
               'false)))
(define (and->if exp)
  (expand-and-clauses (and-clauses exp)))

(define (or? exp)
  (tagged-list? exp 'or))
(define (or-clauses exp) (cdr exp))
(define (expand-or-clauses clauses)
  (if (null? clauses)
      'false
      (make-if (car clauses)
               'true
               (expand-or-clauses (cdr clauses)))))

(define (or->if exp)
  (expand-or-clauses (or-clauses exp)))

The tricky thing is the type of the return value. For derived expression, the returned type is some data, while for other kinds, it would return some code.

4.5

(define (expand-clauses clauses)
  (if (null? clauses)
    'false                          ; no else clause
    (let ((first (car clauses))
          (rest (cdr clauses)))
      (if (cond-else-clause? first)
        (if (null? rest)
          (sequence->exp (cond-actions first))
          (error "ELSE clause isn't last -- COND->IF" clauses))
        (let ((test (cond-predicate first))
              (recepient (if (eq? (car (cond-actions first)) '=>)
                           (cadr (cond-actions first))
                           false)))
          (make-if test
                  (if recepient
                    (list recepient test) ;test-recepient cond
                    (sequence->exp (cond-actions first))) ;normal cond
                  (expand-clauses rest)))))))

4.6

 (define (let? expr) (tagged-list? expr 'let))
 (define let-associations cadr)
 (define (let-vars expr) (map car (let-associations expr)))
 (define (let-value expr) (map cadr (let-associations expr)))
 (define (let-body expr) (cddr expr))
 (define (let->combination expr)
   (cons (make-lambda (let-vars expr) (let-body expr))
         (let-value expr)))

4.7

 (define (let*? expr) (tagged-list? expr 'let*))
 (define (let*-body expr) (caddr expr))
 (define (let*-inits expr) (cadr expr))
 (define (let*->nested-lets expr)
   (let ((inits (let*-inits expr))
         (body (let*-body expr)))
     (define (make-lets exprs)
       (if (null? exprs)
         body
         (list 'let (list (car exprs)) (make-lets (cdr exprs)))))
     (make-lets inits)))

4.8

It should be transformed like this.

(define (fib n)
  (define (fib-iter a b count)
    (if (= count 0)
      b
      (fib-iter (+ a b) a (- count 1))))
  (fib-iter 1 0 n))
 (define (named-let->func expr) 
     (list 'define  
           (cons (named-let-func-name expr) (named-let-func-parameters expr)) 
           (named-let-func-body expr))) 
  
 (define (let->combination expr) 
     (if (named-let? expr) 
         (sequence->exp 
           (list (named-let->func expr) 
                 (cons (named-let-func-name expr) (named-let-func-inits expr)))) 
         (cons (make-lambda (let-vars expr) 
               (list (let-body expr))) 
               (let-inits expr)))) 

4.9

(define (while->combination expr)
  (sequence->exp
    (list (list 'define
                (list 'while-iter)
                (make-if (while-condition expr)
                         (sequence->exp (list (while-body expr)
                                              (list 'while-iter)))
                         'true))
          (list 'while-iter))))
----------------------------------- 本文内容遵从CC版权协议转载请注明出自kamelzcs -----------------------------------
«  | sicp-3-5-4-3-5-5 »

Hide Comments

comments powered by Disqus