(sicp27)m2.73, m2.75, m2.76

問題2.74はまた今度。
(日本語を入力するのが面倒だったので、コメントなども英語になってます。(たぶん文法とか意味もめちゃくちゃです><))

m2.73

;;m2.73
(define (deriv exp var)
  (cond ((number? exp) 0)
        ((variable? exp)
         (if (same-variable? exp var) 1 0))
        ((sum? exp)
         (make-sum (deriv (addend exp) var)
                   (deriv (augend exp) var))
         ((product? exp)
          (make-sum
           (make-product (multiplier exp)
                         (deriv (multiplicand exp) var))
           (make-product (deriv (multiplier exp) var)
                         (multiplicand exp))))
         (else
          (error "unknown expression type -- DERIV" exp)))))

(define (deriv exp var)
  (cond ((number? exp) 0)
        ((variable? exp)
         (if (same-variable? exp var) 1 0))
        (else ((get 'deriv (operator exp) (operands exp)
                    var)))))

(define (operator exp) (car exp))
(define (operands exp) (cdr exp))

;;a.
;; date-directed-programming style apply make-sum, make-product, and anything else. The reason why is because number and symbol is atomic object.

;;b.
(define (install-sum-package)
  ;;internal procedures
  (define (sum? exp)
    (and (pair? exp) (eq? (car exp) '+)))
  (define (addend s) (cadr s))
  (define (augend s)
    (if (null? (cddr s))
        (cadr s)
        (cons '+ (cdr s))))
  (define (make-sum a1 a2)
    (cond ((=number? a1 0) a2)
          ((=number? a2 0) a1)
          ((and (number? a1) (number? a2)) (+ a1 a2))
          (else (list '+ a1 a2))))
  (define (deriv exp var)
    (make-sum (deriv (addend exp) var)
              (deriv (augend exp) var)))
  
  ;;interface to the rest of the system
  (define (tag x) (attach-tag '+ x))
  (put 'make '+ make-sum)
  (put 'deriv '+ deriv))
'done)

(define (install-product-package)
  (install-sum-package)
  (define (product exp)
    (and (pair? exp) (eq? (car exp) '*)))
  (define (multiplier p) (cadr p))
  (define (multiplicand p)
    (if (null? (cddr p))
        (cadr p)
        (cons '* (cdr p))))
  (define (make-product m1 m2)
    (cond ((or (=number? m1 0) (=number? m2 0)) 0)
          ((=number? m1 1) m2)
          ((=number? m2 1) m1)
          ((and (number? m1) (number? m2)) (* m1 m2))
          (else (list '* m1 m2))))
  (define (deriv exp var)
    (make-sum
     (make-product (multiplier exp)
                   (deriv (multiplicand exp) var))
     (make-product (deriv (multiplier exp) var)
                   (multiplicand exp))))

  ;;interface to the rest of the system
  (put 'make '* make-product)
  (put 'deriv '* deriv)
  'done)

;;c.
(define (install-exponent-package)
  (install-product-package)
  (define (exponetiation? exp)
    (and (pair? exp) (eq? (car  exp) '**)))
  (define (base e)  (cadr e))
  (define (exponent exp) (caddr e))
  (define (make-exponetiation b e)
    (cond ((= e 0) 1)
          ((= e 1) b)
          (else (list '** b e))))
  (define (deriv exp var)
    (make-product
     (make-product (exponent exp)
                   (make-exponetiation (base exp) (- (exponent exp) 1)))
     (deriv (base exp) var)))

  ;;interface to the rest of the system
  (put 'make '** make-exponetiation)
  (put 'deriv '** deriv)
  'done)

(define (install-deriv-package)
  (install-exponent-package))

;;d.
;;change such as below
;; (define (operator exp) (cdr exp))
;; (define (operands exp) (car exp))

m2.75, m2.76

;; Message Passing
;;data-directed-programming -> filtering by Object-type
;;message-passing           -> filtering by method

(define (make-from-real-imag x y)
  (define (dispatch op)
    (cond ((eq? op 'real-part) x)
          ((eq? op 'imag-part) y)
          ((eq? op 'magnitude)
           (sqrt (+ (square x) (square y))))
          ((eq? op 'angle) (atan y x))
          (else
           (error "Unknown op -- MAKE-FROM-REAL-IMAG" op))))
  dispatch)

(define (apply-generic op arg) (arg op))

;;m2.75
(define (make-from-mag-ang r a)
  (lambda (op)
    (cond ((eq? op 'magnitude) r)
          ((eq? op 'angle) a)
          ((eq? op 'real-part) (* r (cos a)))
          ((eq? op 'imag-part) (* r (sin a)))
          (else
           (error "Unknown op -- MAKE-FROM-MAG-ANG" op)))))

;;m.2.76
;;i thought the question is when the case need to add new something (type or operator), which approach is editing easier.
;;Maybee.. the answer can be found from Figure 2.22
;; new-operation: message-passing-style
;; new-type:      data-directed-programming-style
;;(a few type & operation: generic operations with explicit dispatch)