SICP問題2.77
実際にエラーが出るかを実験。
(define z (make-complex-from-real-imag 3 4)) ; z z ; (complex rectangular 3 . 4) (magnitude z) ; *** ERROR: No method for these types -- APPLY-GENERIC (magnitude (complex)) ; Stack Trace: ; _______________________________________
動かない理由は magnitude が complex タグで登録されていないから。
(rectangular, polar タグでのみ登録されている)
問題の選択子を追加したcomplexパッケージで実験。
(define (install-complex-package) ;; 直交座標と極座標パッケージから取り入れた手続き (define (make-from-real-imag x y) ((get 'make-from-real-imag 'rectangular) x y)) (define (make-from-mag-ang r a) ((get 'make-from-mag-ang 'polar) r a)) ;; 内部手続き (define (add-complex z1 z2) (make-from-real-imag (+ (real-part z1) (real-part z2)) (+ (imag-part z1) (imag-part z2)))) (define (sub-complex z1 z2) (make-from-real-imag (- (real-part z1) (real-part z2)) (- (imag-part z1) (imag-part z2)))) (define (mul-complex z1 z2) (make-from-real-imag (* (magnitude z1) (magnitude z2)) (* (angle z1) (angle z2)))) (define (div-complex z1 z2) (make-from-real-imag (/ (magnitude z1) (magnitude z2)) (- (angle z1) (angle z2)))) ;; システムの他の部分へのインタフェース (define (tag z) (attach-tag 'complex z)) (put 'add '(complex complex) (lambda (z1 z2) (tag (add-complex z1 z2)))) (put 'sub '(complex complex) (lambda (z1 z2) (tag (sub-complex z1 z2)))) (put 'mul '(complex complex) (lambda (z1 z2) (tag (mul-complex z1 z2)))) (put 'div '(complex complex) (lambda (z1 z2) (tag (div-complex z1 z2)))) (put 'make-from-real-imag 'complex (lambda (x y) (tag (make-from-real-imag x y)))) (put 'make-from-mag-ang 'complex (lambda (r a) (tag (make-from-mag-ang r a)))) (put 'real-part '(complex) real-part) (put 'imag-part '(complex) imag-part) (put 'magnitude '(complex) magnitude) (put 'ange '(complex) angle) 'done) (install-complex-package) ; done ; 再度、実行 (magnitude z) ; 5.0
動いた!!
働く理由は以下のような感じ。
実際に登録されている関数を参照するとmagnitudeは
(magnitude (rectangular) #<closure (install-rectangular-package magnitude)>) (magnitude (polar) #<closure (install-polar-package magnitude)>) (magnitude (complex) #<closure magnitude>)
となっている。
つまり complex タグがついたデータでmagnitudeを実行すると、内部では complex タグが剥されたデータで rectanglar か polar の magnitudeが呼び出されるからである。このため apply-generic は二回呼び出される。