timothy235 icon

sicp-2-4-multiple-representations-for-abstract-data

timothy235 | PRO | 12/19/24 01:17:54 AM UTC (Edited) | 0 ⭐ | 4103 👁️ | Never ⏰ | []
Racket |

5.66 KB

|

None

|

0 👍

/

0 👎

#lang racket
 
;;;;;;;;;;
;; 2.73 ;;
;;;;;;;;;;
 
(define deriv-table (make-hash))
(define (put type item) (hash-set! deriv-table type item))
(define (get type) (hash-ref deriv-table type))
 
(define (=number? x y) (and (number? x) (number? y) (= x y)))
(define (variable? x) (symbol? x))
(define (same-variable? v1 v2)
  (and (variable? v1) (variable? v2) (eq? v1 v2)))
(define (operator expr) (first expr))
(define (operands expr) (rest expr))
 
(define (deriv expr var)
  (cond [(number? expr) 0]
        [(variable? expr) (if (same-variable? expr var) 1 0)]
        [else ((get (operator expr)) (operands expr) var)]))
 
;; a.  number? and same-variable? cannot be put in the op table because they do
;; not operate on tagged expressions.
 
;; constructors and selectors
(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 (addend s) (first s))
(define (augend s) (second s))
(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 (multiplier p) (first p))
(define (multiplicand p) (second p))
(define (make-exponentiation base expo)
  (cond [(=number? expo 0) 1]
        [(=number? expo 1) base]
        [(and (number? base) (number? expo)) (expt base expo)]
        [else (list '** base expo)]))
(define (base e) (first e))
(define (exponent e) (second e))
 
(define (install-differentiation-rules)
  (define (sum-rule expr var)
    (make-sum (deriv (addend expr) var)
              (deriv (augend expr) var)))
  (define (product-rule expr var)
    (make-sum (make-product (deriv (multiplier expr) var)
                            (multiplicand expr))
              (make-product (multiplier expr)
                            (deriv (multiplicand expr) var))))
  (define (power-rule expr var)
    (make-product (exponent expr)
                  (make-product (make-exponentiation (base expr)
                                                     (sub1 (exponent expr)))
                                (deriv (base expr) var))))
  (put '+ sum-rule)
  (put '* product-rule)
  (put '** power-rule))
 
(install-differentiation-rules)
 
(deriv '(+ (* x y) (** x 3)) 'x)
;; '(+ y (* 3 (** x 2)))
(deriv '(+ (* x y) (** x 3)) 'y)
;; 'x
 
;; d.  If we indexed procedures by type and operator instead of by operator and
;; type we would only have to change put and get by interchanging the
;; parameters.  Everything else would work the same.
 
;;;;;;;;;;
;; 2.74 ;;
;;;;;;;;;;
 
;; We need to create a proc table indexed by operation and type.  The divisions
;; are the types, and the proc table would yield the correct procedure for that
;; operation that worked on that division's files.
 
(define (get-record division name)
  ((get 'record division) name))
 
(define (get-salary division name)
  ((get 'salary division) name))
 
(define (find-employee-record name divisions)
  (cond [(null? divisions)
         (error "name not found -- FIND-EMPLOYEE-RECORD" name)]
        [else
          (define record (get-record (first divisions) name))
          (or record
              (find-employee-record name (rest divisions)))]))
 
;; When acquiring a new division, headquarters will have to add a new column of
;; procedures to the proc table.
 
;;;;;;;;;;
;; 2.75 ;;
;;;;;;;;;;
 
(define (make-from-mag-ang r a)
  (define (dispatch op)
    (cond [(eq? op 'real-part) (* r (cos a))]
          [(eq? op 'imag-part) (* r (sin a))]
          [(eq? op 'magnitude) r]
          [(eq? op 'angle) a]
          [else (error "unknown op --  MAKE-FROM-MAG-ANG" op)]))
  dispatch)
 
;;;;;;;;;;
;; 2.76 ;;
;;;;;;;;;;
 
;; We want to write a program that performs different operations on a data object
;; represented in different ways.  For each operation and each representation,
;; there will be a different procedure that implements that operation on that
;; representation.  How do we organize all these procedures to make later
;; modifying our program as simple as possible?
 
;; There are three possibilities:
 
;; We can sort the procedures by operation, and have one definition for each
;; operation that contains all the procedures implementing that operation on all
;; the different representations.  This is the direct dispatch method.  The
;; operations are called generic operations because they operate on data
;; represented in different ways.  Direct dispatch is a good method if you think
;; you'll be adding new operations but no new representations because then you
;; only need to add a new definition for each new operation without modifying the
;; definitions of the already implemented operations.
 
;; We could also sort the procedures by representation type, and then define a
;; dispatch function for each type that takes an operation as a parameter and
;; returns the correct procedure that implements that operation on that
;; representation type.  This is the message-passing style.  Message-passing is a
;; good method if you'll be adding new types but no new operations because then
;; you only need to add a new dispatch definition for each new representation
;; without modifying the dispatch functions of the other already implemented
;; types.
 
;; The third possibility is to sort the procedures by operation and type, and
;; store all the procedures in a two-dimensional table.  This is data-driven
;; programming.  Data-driven programming is a good choice whether you'll be adding
;; new operations or new types, but it's best if you'll be adding both.

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎