SICP 読み (31) 2.2.4 例: 図形言語

stub の実装を検討するのが面倒なので試験ドリブンは略。
図 2.9 の手続きも紹介されている。

(defiine (square-limit painter n)
  (let ((quater (corner-split painter n)))
    (let ((half (beside (flip-horiz quater) quater)))
      (below (flip-vert half) half))))

ざっくりベースな処理として、元画像と元画像を左右反転させたナニと、そのナニを上下反転させたソレを below する、と。実装は置いとくとして、意味が分かりやすい、というのも抽象表現のおかげか。

動作するかどうかは置いといて、問題 2.44 の解と思われる手続きを以下に。

(define (up-split painter n)
  (if (= n 0)
      painter
      (let ((smaller (up-split painter (- n 1))))
	(below painter (beside smaller smaller)))))

とりあえず、実装に拘らずに検討した方が良さげな感じがする。

高階演算

パターンの抽象化ですか。括弧で括る、という作業に似てはいるが、マトメた結果できるのが手続きってあたりが算数と違うのか。小学校あたりでこんなソレを教えてくれてたら、もう少し日本とゆー国も違ってくるんじゃね??という微妙なナニはさて置き。

問題 2.45 は上記な作業を要求しているな。動作確認できんので、間違えてるかもしれん、というのを前提に以下。

(define (split p1 p2)
  (lambda (painter n)
    (let f ((painter painter) (n n))
      (if (= n 0)
	  painter
	  (let ((smaller (f painter (- n 1))))
	    (p1 painter (p2 smaller smaller)))))))

フレーム

うーん。スルーしすぎなのかなぁ。なんか落ちてない感満載。あ、原点が mapping できればあとはベクタだから良いのか??
とりあえず以下に問題 2.46 の解を。

(define (make-vect x y)
  (list x y))

(define (xcor-vect v)
  (car v))

(define (ycor-vect v)
  (cadr v))

(define (add-vect v1 v2)
  (make-vect (+ (xcor-vect v1)
		(xcor-vect v2))
	     (+ (ycor-vect v1)
		(ycor-vect v2))))

(define (sub-vect v1 v2)
  (make-vect (- (xcor-vect v1)
		(xcor-vect v2))
	     (- (ycor-vect v1)
		(ycor-vect v2))))

(define (scale-vect s v)
  (make-vect (* s (xcor-vect v)) (* s (ycor-vect v))))

問題 2.47 も以下に。このパターンは試験ドリブンにしておくと確認が楽だな。てーか楽ちんすぎて本当に良いのかどうか不安になるな。

まず一つめ。

(define (make-frame origin edge1 edge2)
  (list origin edge1 edge2))

選択子 (selector) は以下。

(define (origin-frame f)
  (car f))

(define (edge1-frame f)
  (cadr f))

(define (edge2-frame f)
  (caddr f))

次は以下。

(define (make-frame origin edge1 edge2)
  (cons origin (cons edge1 edge2)))

選択子 (selector) は以下。

(define (origin-frame f)
  (car f))

(define (edge1-frame f)
  (cadr f))

(define (edge2-frame f)
  (cddr f))

次の節あたりから具体的になってくるか。