SICP 読み (73) 2.5.3 例: 記号代数

へろへろながら、試験を書く準備までできた。しかし、関数の中に関数が書いてある場合の単体試験ってどうやるんだろうか。scheme 無知なだけ、という話もあるんですが、java とか ruby なんかでも private なメソドの単体試験って一体どんなして書くんだろうか。
RoR で単体試験を書きナグッてるはずなんですが記憶ナシ。多分漏らしてるんだろうな。(とほほほ
一応以下に現時点での実装を。

(require "2.5.2")

(define (install-polynomial-package)
  (define (adjoin-term term term-list)
    (if (=zero? (coeff term))
	term-list
	(cons term term-list)))
  (define (the-empty-termlist) '())
  (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 (make-term order coeff) (list order coeff))
  (define (order term) (car term))
  (define (coeff term) (cadr term))

  (define (make-poly variable term-list)
    (cons variable term-list))
  (define (variable p) (car p))
  (define (term-list p) (cdr p))

  (define (variable? x) (symbol? x))
  (define (same-variable? v1 v2)
    (and (variable? v1) (variable? v2) (eq? v1 v2)))

  (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 (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-poly p1 p2)
    (if (same-vaeiable? (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 (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 (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 (tag p) (attach-tag 'polynomial p))
  (put 'add '(polynomial polynomial)
       (lambda (p1 p2) (tag (add-poly p1 p2))))
  (put 'mul '(polynamial 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))

require してる 2.5.2.scm は強制型変換が盛り込まれている版です。make-polynomial な確認のみを盛り込んだ試験が以下。

#!/usr/bin/env gosh

(use math.const)
;(use test.unit)
(require "2.5.3")

(define-test-suite "2.5.3"

  ("make-polynomial test"
   (setup (lambda ()
	    (install-polynomial-package)))

   ("car is 'polynomial"
    (assert-equal 'polynomial (car (make-polynomial 'var 'terms)))
    )

   ("cadr is var"
    (assert-equal 'var (cadr (make-polynomial 'var 'terms)))
    )

   ("cddr is terms"
    (assert-equal 'terms (cddr (make-polynomial 'var 'terms)))
    )
   )
  )

練習問題やる前に実装の動作確認な試験を書こうとしているんですが、この時点でハードルが高いというのもナニですな。