帶有顯式分派的通用性操作
在加入一個新類型時,需要添加新類型的構造過程、選擇過程、各自通用操作過程,另外還需要在通用操作過程中加入數據標識的判斷,根據數據標識執行相應的數據類型過程。
而如果需要添加新操作,則需要在每一種類型裏面添加各自的新的操作,還需要添加新操作的通用過程。
拿書中複數的實現舉例添加新類型需要修改的編碼。
#lang racket
//加入新類型的構造過程和選擇過程
(define (real-part-polar z)
(* (magnitude-polar z) (cos (angle-polar z))))
(define (imag0part-polar z)
(* (magnitude-polar z) (sin (angle-polar z))))
(define (magintude-polar z) (car z))
(define (angle-polar z) (cdr z))
(define (make-from-real-imag-polar x y)
(attach-tag 'polar
(cons (sqrt (+ (square x) (square y)))
(atan y x))))
(define (make-from-mag-ang-polar r a)
(attach-tag 'polar (cons r a)))
//加入標識判斷
(define (reak-part z)
(cond ((rectangular? z)
(real-part-rectangular (contents z)))
((polar? z)
(real-part-polar (contents z)))
(else (error "Unknown type -- REAL-PART" z))))
不論添加新類型還是新操作都需要修改大量代碼來實現。
數據嚮導風格
在加入一個新類型時,需要添加新類型的過程包就可以,其他地方不需要變動。
#lang racket
(define (install-polar-package)
(define (magnitude z) (car z))
(define (angle z) (cdr z))
(define (make-from-mag-ang r a) (cons r a))
(define (real-part z)
(* (magnitude z) (cos (angle z))))
(define (imag-part z)
(* (magnitude z) (sin (angle z))))
(define (make-from-real-imag x y)
(cons (sqrt (+ (square x) (square y)))
(atan y x)))
(define (tag x) (attach-tag 'polar x))
(put 'real-part '(polar) real-part)
(put 'imag-part '(polar) imag-part)
(put 'magnitude '(polar) magnitude)
(put 'angle '(polar) angle)
(put 'make-from-real-imag '(polar)
(lambda (x y) (tag (make-from-real-imag x y))))
(put make-from-mag-ang '(polar)
(lambda (r a) (tag (make-from-mag-ang r a))))
'done)
如果添加新操作,也可以添加一個安裝包,這個安裝包裏面包含每一種類型對應新操作的過程,比如下面這種方式。
(define (install-newop-package)
(define (newop-rectangular z)
(car z))
(define (newop-polar z)
(car z))
(put 'newop '(rectangular) newop-rectangular)
(put 'newop '(polar) newop-polar))
(define (newop z) (apply-generic 'newop z))
這種方式有操作信息表,比較靈活,不管是添加新類型或者新操作,只要操作“操作信息表”就可以。
消息傳遞的風格
在加入一個新類型時,需要添加新類型的構造程序就可以,其他地方不需要變動。
(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)
如果添加新操作,則需要每一個構造過程加入新的操作函數。
(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)
((eq? op 'newop) (square r))
(else
(error "Unknown op -- MAKE-FROM-MAG-ANG" op))))
dispatch)
消息傳遞的風格,不需要過多的選擇函數,代碼量比較小,但是添加新操作比較麻煩,每種都需要添加。