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 は二回呼び出される。