SICP 読み (70) 2.5.2 異る型のデータの統合

休みとゆー事で公園に本を持っていった。問題 2.85 を再読 (後天性記憶不全です) していると註釈を発見。round 使うとの記述。
直前エントリ (SICP 読み (69)) では切りステ、等書いてあるがとりあえず round と floor の実装の差が以下。

gosh> (floor 5.5)
5.0
gosh> (round 5.5)
6.0
gosh> (floor 5.4)
5.0
gosh> (round 5.4)
5.0
gosh> 

round は四捨五入で floor は切りステらしい。ただ、SICP の件の註釈を引用すると

実数は整数へ、引数に最も近い整数を返す round 手続きを使って投影することができる。

とある。たしかにこれはこれで成程かも。ただ、動作としてはどっちでもええと言えばええんだろな、という事でバグではないと判断。floor を round に戻さずにやってみる。


まず、apply-generic に盛り込む前に drop 単体での試験を検討してみる。SICP に記述があるソレ的が以下とすると

試験としては以下ッスか。

  ("drop test"
   (setup (lambda ()
	    (install-integer-package)
	    (install-rational-package)
	    (install-real-package)
	    (install-complex-package)
	    (install-rectangular-package)
	    (install-polar-package)))

   ("complex _1.5 + 0i_ can drop real"
    (let ((t1 (make-complex-from-real-imag 1.5 0)))
      (assert-equal 'real (type-tag (drop t1)))
      (assert-true (equ? (make-real 1.5) (drop t1))))
    )
   
   ("complex _1.0 + 0i_ can drop integer"
    (let ((t1 (make-complex-from-real-imag 1.0 0)))
      (assert-equal 'integer (type-tag (drop t1)))
      (assert-true (equ? (make-integer 1) (drop t1))))
    )

   ("complex _2 + 3i_ cannot drop"
    (let ((t1 (make-complex-from-real-imag 2 3)))
      (assert-equal 'complex (type-tag (drop t1)))
      (assert-equal (equ? t1 (drop t1))))
   )


で、実装の検討なんですが、

  • integer パケジには project 手続きが実装されていない。lower を get-raise して '() が戻る場合には一番下、という判断をする必要あり。
  • 後は基本的に project した値と raise な値の比較

なカンジですか。でっち上げた手続きが以下。一応上記の試験にはパスしています。

(define (drop x)
  (let f ((x x))
    (if (null? (get-raise (type-tag x) 'lower))
	x
	(let ((prj (project x)) (before x))
	  (if (not (equ? (raise prj) before))
	      before
	      (f prj))))))

備忘録

  • 試験はまだ足らない (= バグっている可能性あり)
  • 検討の時間が空けば空くほど再開が微妙になる (kernel の件で経験済み)
  • このまま apply-generic に盛り込めるんだろうか

とは言え、こっち稼働の確保が現状では相当に (以下略