SICP §2.2.4(図形言語 その4 [ペインタの生成・変換])
前エントリの wave4 は、まず wave2 を定義してから、beside と絡めて生成しているが、wave2 を生成しなくても生成できたりする。
(define (flipped-paires painter) (let ((painter2 (beside painter (flip-vert painter)))) (below painter2 painter2))) (define wave4 (flipped-pairs wave))
更に、再帰を使うことで、曼荼羅のような図を描画することも可能とのこと。こんな感じで。
;右側を上下に分割して、その中に更に自分を適用していく処理を n 回繰り返すペインタ。 (define (right-split painter n) (if (= n 0) painter (let ((smaller (right-split painter (- n 1)))) (beside painter (below smaller smaller))))) ;左下を基準として、右側、上側に向かって n 回の再帰描画をしていくペインタ (define (corner-split painter n) (if (= n 0) painter ;up-splitで上方向に(おそらく)再帰するペインタを生成。 ;right-splitで右方向に再帰するペインタを生成。 (let ((up (up-split painter (- n 1))) (right (right-split painnter (- n 1)))) ;4分割したうちの、左上、右下、右上のペインタを生成する。 (let ((top-left (beside up up)) (bottom-right (below right right)) (corner (conrer-split painter (- n 1)))) ;生成したペインタ群を使用して描画を行う。 (beside (below painter top-left) (below bottom-right corner)))))) ;(おそらく)曼荼羅のように描画していくペインタを生成 (define (square-limit painter n) (let ((quarter (corner-split painter n))) ;flip-horiz で、(おそらく)quarter を横方向に反転したペインタを生成 (let ((half (beside (flip-horiz quarter) quarter))) ;flip-vert で、(おそらく)half を縦方向に反転したペインタを生成 (below (flip-vert half) half))))
さて、ここで定義がまだ生成されていない手続がいくつかあるので、一応整理しておこう。
;引数のペインタを使って水平方向に描画するペインタを生成 (define (beside left-painter right-painter) ...) ;引数のペインタを使って垂直方向に描画するペインタを生成 (define (below down-painter up-painter) ...) ;引数のペインタを横方向に反転したペインタを生成 (define (flip-horiz painter) ...) ;引数のペインタを縦方向に反転したペインタを生成 (define (flip-vert painter) ...) ;引数のペインタを上方向に n 回再帰して描画するペインタを生成 (define (up-split painter n) ...)
SICPの方では、最後の up-split 手続以外のペインタ生成手続についても具体的な定義には触れていない。。(だからわかんなくなっちまうんだよぉ。)
最後の up-split については「問題 2.44」で定義を導き出すようになっている。
疑問点
さて、もう一つ疑問があるんだが、beside や below はいい、まだ理解できる。んが、
どーやって実現すんだろう??
flip-* 手続は、描画方向がまったく逆になる。beside や below で構成要素となるペインタの位置を明確に決定しているが、それを反転変換することが可能なのか?