SICP 読み (57) 2.5.1 汎用算術演算
問題 2.77 です。問題の状況を再現してみる。ここでは、p.107 にて提示されている以下の手続きを定義している事を前提に。
(define (real-part z) (apply-generic 'real-part z)) (define (imag-part z) (apply-generic 'imag-part z)) (define (magnitude z) (apply-generic 'magnitude z)) (define (angle z) (apply-generic 'angle z))
で、定義をばくっと gosh に流しこんで以下。
gosh> (install-complex-package) done gosh> (install-polar-package) done gosh> (install-rectangular-package) done gosh> (make-complex-from-real-imag 3 4) (complex rectangular 3 . 4) gosh> magnitude #<closure magnitude> gosh> (magnitude (make-complex-from-real-imag 3 4)) *** ERROR: No method for these types -- APPLY-GENERIC (magnitude (complex)) Stack Trace: _______________________________________ gosh>
確かに complex なパケジには magnitude なんてインターフェースはないわな。
でも Alyssa さんが言うように単純に complex なパケジにインターフェースを追加して動作するのは何故なんだ、という事を調べてみる。まず動作を。
gosh> (install-complex-package) done gosh> (install-polar-package) done gosh> (install-rectangular-package) done gosh> (make-complex-from-real-imag 3 4) (complex rectangular 3 . 4) gosh> magnitude #<closure magnitude> gosh> (magnitude (make-complex-from-real-imag 3 4)) 5.0 gosh>
上記の最後の手続きを置き換えてみるか。
(magnitude (make-complex-from-real-imag 3 4)) (magnitude '(complex rectangular 3 . 4)) (apply-generic 'magnitude '(complex rectangular 3 . 4)) (apply (get 'magnitude (map type-tag '((complex rectangular 3 . 4)))) (map contents '((complex rectangular 3 . 4)))) (apply (get 'magnitude '(complex)) '((rectangular 3 . 4))) (apply magnitude '((rectangular 3 . 4))) ;; complex の magnitude (magnitude '(rectangular 3 . 4)) (apply-generic 'magnitude '(rectangular 3 . 4)) (apply (get 'magnitude (map type-tag '((rectangular 3 . 4)))) (map contents '((rectangular 3 . 4)))) (apply (get 'magnitude '(rectangular)) '((3 . 4))) (apply magnitude '((3 . 4))) ;; rectangular の magnitude (sqrt (+ (square (real-part '(3 . 4))) (square (imag-part '(3 . 4)))))
これ、頭の中では考えられんな。てーか、これって継承??
カワを剥いでいく感じがなんか不思議です。
合ってるのかどうか微妙なんで gosh でトレイスしたいんだけど、どうやるんだったか。と言いつつ google 先生に伺ってみると、dankogai さんのエントリが。
で、(use slib) して (require 'trace) すれば良いのね、と言いつつやってみると叱られる。gaunit 使うために testing な debian 使ってるんですが
*** ERROR: unbound variable: slib:features Stack Trace: _______________________________________ dpkg: error processing gauche (--configure): subprocess post-installation script returned error exit status 1 Errors were encountered while processing:
みたいな感じ。面倒なので chroot じゃない環境でトレイスは確認しよう。
gosh> (magnitude (make-complex-from-real-imag 3 4)) CALL magnitude (complex rectangular 3 . 4) CALL magnitude (rectangular 3 . 4) RETN magnitude 5.0 RETN magnitude 5.0 5.0 gosh>
むむ。apply-generic も追加。
gosh> (trace apply-generic) #<closure 0x850a920(args)> gosh> (magnitude (make-complex-from-real-imag 3 4)) CALL magnitude (complex rectangular 3 . 4) CALL apply-generic magnitude (complex rectangular 3 . 4) CALL magnitude (rectangular 3 . 4) CALL apply-generic magnitude (rectangular 3 . 4) RETN apply-generic 5.0 RETN magnitude 5.0 RETN apply-generic 5.0 RETN magnitude 5.0 5.0 gosh>
合ってるんだと信じたい。(を
追記
置き換えなソレは検証してないな、ということで gosh に吸わせて動作確認してみたんですが、最後のふたつは隠蔽された手続きになるため、gosh 上では確認できず。(当り前か