開発環境
- OS X Lion - Apple(OS)
- Emacs、BBEdit - Bare Bones Software, Inc. (Text Editor)
- プログラミング言語: MIT/GNU Scheme
計算機プログラムの構造と解釈(Gerald Jay Sussman(原著)、Julie Sussman(原著)、Harold Abelson(原著)、和田 英一(翻訳)、ピアソンエデュケーション、原書: Structure and Interpretation of Computer Programs (MIT Electrical Engineering and Computer Science)(SICP))の2(データによる抽象の構築)、2.5(汎用演算のシステム)、2.5.2(異なる型のデータの統合)、強制型変換、型の階層構造、階層構造の不適切さの問題 2.81、問題 2.82、問題 2.83、問題 2.84を解いてみる。
その他参考書籍
問題 2.81
a.
無限ループが起きる。
b.
無限ループが起きるので、Louisは正しくない。
c.
コード
sample.scm
(define (apply-generic op . args) (let ((type-tags (map type-tag 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))) (if (eq? type1 type2) (error "No method for these types" (list op type-tags))) (let ((a1 (car args)) (a2 (cadr args)) (t1->t2 (get-coercion type1 type2)) (t2->t1 (get-coercion type2 type1))) (cond (t1->t2 (apply-generic op (t1->t2 a1) a2)) (t2->t1 (apply-generic op a1 (t2->t1 a2))) (else (error "No method for these types" (list op type-tags)))))) (error "No method for these types" (list op type-tags)))))))
問題 2.82
コード
sample.scm
(define (apply-generic op . args) ;; リストの全ての要素をtypeに変換したリストを返す手続き ;; 変換できない要素がある場合は偽を返す (define (iter type args result) (if (null? args) result (let ((t1->t2 (get-coercion (type-tag (car args))))) (if t1->t2 (iter type (cdr args) (append result (list (t1->t2 (car args))))) false)))) ;; 第一引数の型、次に第に引数の型等々に順に強制変換を試みて ;; 強制変換できて、さらに演算できるなら演算する (define (iter-1 types) (if (null? types) (error "No method for these types" (list op type-tags)) (let ((args-1 (iter (car types) args '()))) (if args-1 (let ((type-tags (map type-tag args-1))) (let ((proc (get op type-tags))) (if proc (apply proc (map contents args-1)) (error "No method for these types" (list op type-tags))))) (iter-1 (cdr types)))))) (let ((type-tags (map type-tag args))) (let ((proc (get op type-tags))) (if proc (apply proc (map contents args)) (iter-1 type-tags)))))
この戦略が十分に一般的ではない状況は、引数が互いのいずれかの型に変換できなくても、引数にはない共通の拡大型に変換できて、演算可能という可能性は考慮していないこと。
問題 2.83
コード
sample.scm
;; 追加個所のみ ;; scheme-numberパッケージは整数と実数の2つのパッケージに変更 ;; 整数のパッケージに追加 ;; install-int-package (define (int->rational x) (make-rational x 1)) (put 'raise '(scheme-number) int->rational) ;; 有理数のパッケージに追加 ;; install-rational-package (define (rational->real x) (make-real x)) (put 'raise '(rational) rational->real) ;; 実数用のパッケージを新たに作ったと仮定 ;; 実数のパッケージに追加 ;; install-real-package (define (real->complex x) (make-complex-from-real-imag x 0)) (put 'raise '(real) real->complex) ;; 汎用演算胃 (define (raise x) (apply-generic 'raise x))
問2.84
p>コードsample.scm
(define (apply-generic op . args) (define (higher t1 t2) (define tower '(complex real rational int)) (define (iter tower) (if (null? tower) false (let ((t (car tower))) (cond ((eq? t1 t) t1) ((eq? t2 t) t2) (else (iter (cdr tower))))))) (iter tower)) (define (highest types) (define (iter types highest) (if (null? types) highest (iter (cdr types) (higher (car types) highest)))) (iter (cdr types) (car types))) (define (raise-iter x type) (if (eq? (type-tag x) type) x (raises (raise-iter x) type))) (let ((highest-tag (highest args))) (let ((arg-1 (raise-iter args))) (let ((type-tags (map (type-tag args-1)))) (let ((proc (get op type-tags))) (if proc (apply proc (map contents args-1)) (error "No method for these types" (list op type-tags))))))))
とりあえず書いてはみたものの、引数の型の個数に問題がありそうな。。
0 コメント:
コメントを投稿