SICP 問題 2.45(right-split と up-split を、手続きを返す手続き split を使って具体化してみる)

問題

right-split と up-split は汎用分割演算の具体化として表すことができる。

(define right-split (split beside below))
(define up-split (split below beside))

の評価が既に定義したものと同じ振る舞いの手続き right-split と up-split を作り出すような性質を持つ手続き split を定義せよ。

解答

まずは二つを見比べてみよう。

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

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

で、とりあえず共通するところを split に定義してみちゃう。
あ、split は手続きを返す手続きだから、一番外側は lambda 式になることに注意。

(define (split first second)
  (lambda (painter n)
    (if (= n 0)
	painter
	(let ((smaller ((split first second) painter (- n 1))))
	  (first painter (second smaller smaller))))  

再帰呼び出しの箇所は、split を再帰的に呼び出して lambda 式を受け取り、その手続きに対して painter と n-1 を渡す感じ。