(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)