復習もおわったので問題に戻ります
問題解答
問2.84
問題を前にして考えるものの、どうにも手が動かないので先人の知恵を借りて学習することに。”二つの型のいずれが塔の中で高いかをテストする”というのがイマイチ思い浮かばない。
Python ならリストに入れてインデックスで調べるとか、辞書に入れて優先順位をつけたタグで調べるとかできるんだけど。
そもそも、 Gauche 標準機能だとリスト中で指定した値が格納されているインデックスを取るっていう直接の方法が無いのか。
先人の知恵を見ても、自分で作っている。
;塔の順序リスト
(define tag-tower '(scheme-number rational real complex))
;指定したタグのインデックスを返却
(define (index tag)
(let ((order (member tag tag-tower)))
(if (eq? #f order)
(error "No match type -- HIGHER~INDEX?" tag)
(- (length tag-tower) (length order)))))
“等しい”っていうのが場合によって異なるから定義できないってことなのかな?
レベルの高いタグを返す本体はこんな感じ。
(define (higher? x y)
(let ((idxx (index x))
(idxy (index y)))
(if (< idxx idxy)
x
y)))
apply-generic はこんな感じになるのかな(コードは書いたけど実行はしていない)
(define (apply-generic op . args)
(let ((type-tags (map type-tags args)))
(let ((proc (get op type-tags)))
(if proc
(apply proc (map contents args))
(if (= (length args) 2)
(let ((type1 (car type-tags))
(type2 (cadr type-tags))
(a1 (car args))
(a2 (cadr args)))
(if (eq? type1 type2)
(apply proc (map contents args))
(if (eq? (higher? type1 type2) type1)
(apply-generic op a1 (raise a2))
(apply-generic op (raise a1) a2))))
(error "No method for these types"
(list op type-tags)))))))
問2.85
こんな感じで project を各パッケージ毎に定義して、drop を定義するのかな。
(define (complex->scheme-number x)
(make-scheme-number (real-part (contents x))))
(put 'project 'complex complex->scheme-number)
(define (project x)
(apply-generic 'project x))
(define (drop x)
(let ((p (project x)))
(let ((r (raise p)))
(if (eq x r)
p
x))))