Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #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.
Add Comment
Please, Sign In to add comment