SICP §2.5.3 記号代数
最後の10問の前にこんな重めのセクションが・・・もう3章行きてぇ〜。
つーわけで、今までの汎用演算システムに、代数的な要素も入れちゃおうという話。
このセクションでは多項式(polynomial)を演算対象に含めることを目的とするらしい。
パッケージとして多項式の演算処理を実装するので、こんな手続きが必要になってinstall-polynomial-package手続きの中に定義する感じになる。もっと必要になるかもしれんけど。
更に、多項式は「項」と「変数」で構成されているので、こんな手続きも必要になる。- 項の構成子
- 項の選択子
- 項の述語
- 変数の述語
- 項の加算処理(減算は不要)
- 項の乗算処理(除算も不要?あった方が便利な気がするけど。。)
じゃ、パッケージを作成してみよう。注意点がいくつかあるけど、ソースコード中にコメントで記入しておいた。備忘録として。
(define (install-polynomial-package) ;;============================== ;;内部手続き ;;============================== ;;------------------------------ ;;変数の表現 ;述語 (define (variable? x) (symbol? x)) (define (same-variable? v1 v2) (and (variable? v1) (variable? v2) (eq? v1 v2))) ;;------------------------------ ;;項の表現 ;構成子(※ 項の表現は、'(次数 係数) という感じ。) (define (make-term order coeff) (list order coeff)) ;選択子 (define (order term) (car term)) ;次数 (define (coeff term) (cadr term)) ;係数 ;;------------------------------ ;;項リストの表現 ;選択子 (define (first-term term-list) (car term-list)) (define (rest-terms term-list) (cdr term-list)) ;述語 (define (empty-termlist? term-list) (null? term-list)) ;その他 (define (the-empty-termlist) '()) (define (mul-term-by-all-terms t1 L) (if (empty-termlist? L) (the-empty-termlist) (let ((t2 (first-term L))) (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2))) (mul-term-by-all-terms t1 (rest-terms L)))))) (define (adjoin-term term term-list) (if (=zero? (coeff term)) term-list (cons term term-list))) ;加算 (define (add-terms L1 L2) (cond ((empty-termlist? L1) L2) ((empty-termlist? L2) L1) (else (let ((t1 (first-term L1)) (t2 (first-term L2))) (cond ((> (order t1) (order t2)) (adjoin-term t1 (add-terms (rest-terms L1) L2))) ((< (order t1) (order t2)) (adjoin-term t2 (add-terms L1 (rest-terms L2)))) (else (adjoin-term (make-term (order t1) (add (coeff t1) (coeff t2))) (add-terms (rest-terms L1) (rest-terms L2))))))))) ;乗算 (define (mul-terms L1 L2) (if (empty-termlist? L1) (the-empty-termlist) (add-terms (mul-term-by-all-terms (first-term L1) L2) (mul-terms (rest-terms L1) L2)))) ;;------------------------------ ;;多項式の表現 ;構成子 (define (make-poly variable term-list) (cons variable term-list)) ;選択子 (define (variable p) (car p)) ;変数 (define (term-list p) (cdr p)) ;項リスト ;加算 (define (add-poly p1 p2) (if (same-variable? (variable p1) (variable p2)) (make-poly (variable p1) (add-terms (term-list p1) (term-list p2))) (error "Polys not in same var -- ADD-POLY" (list p1 p2)))) ;乗算 (define (mul-poly p1 p2) (if (same-variable? (variable p1) (variable p2)) (make-poly (variable p1) (mul-terms (term-list p1) (term-list p2))) (error "Polys not in same var -- MUL-POLY" (list p1 p2)))) ;;------------------------------ ;;その他処理 ;タグ付け (define (tag p) (attach-tag 'polynomial p)) ;;============================== ;;システムの他の部分とのインタフェース ;;============================== (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2)))) (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2)))) (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))) 'done) ;外部からコールされる多項式の構成子を定義 (define (make-polynomial var terms) ((get 'make 'polynomial) var terms))
こんなとこか。=zero?手続きが未定義だが、これは問題2.86で出題されているので次のエントリで作成しよう。