2.2 계층 구조 데이터와 
닫힘 성질 
Structure and Interpretation of Computer Programs 
aceigy6322@gmail.com 2014.10.18
상자와 화살표 쌍을 나타내기 
닫힘 성질로 계층 구조 
표현 가능 
- 차례열(Sequence) 
- 나무(Tree) 
- 그림 언어(Graphic)
2.2.1 차례열(Sequence) 표현 방법 
(cons ⟨a1⟩ 
(cons ⟨a2⟩ 
(cons : : : 
(cons ⟨an⟩ 
nil): : :))) 
(list ⟨a1⟩ ⟨a2⟩ : : : ⟨an⟩) 
리스트 - Cons를 겹쳐 만든 쌍의 차례열 
(define one-through-four (list 1 2 3 4)) 
• one-through-four 
- (1 2 3 4) 
• (car one-through-four) 
- 1 
• (cdr one-through-four) 
- (2 3 4) 
• (car (cdr one-through-four)) 
- 2 
• (cons 10 one-through-four) 
- (10 1 2 3 4)
리스트 연산 
• ‘cdr연산을 가지고 흝어 내려가는’ 프 
로그램 기법으로 리스트 연산을 만 
듬. 
• List-ref 프로시져 - 리스트와 수 N 
을 인자로 받아서, 그 리스트의 n번 
째 원소를 내놓음. 
• List-ref 규칙 
– N = 0이면, list-ref의 값은 리스트의 
car 이다. 
– 그렇지 않으면, list-ref는 리스트의 
cdr에서 n-1번째 원소다. 
(define (list-ref items n) 
(if (= n 0) 
(car items) 
(list-ref (cdr items) (- n 1)))) 
(define squares (list 1 4 9 16 25)) 
(list-ref squares 3) 
16
리스트 연산 
• length 프로시져 - 리스트를 인자로 
받아 리스트의 원소가 몇 개인지 찾 
음. 
• length 규칙 
– 리스트의 length는 그 리스트의 cdr 
의 length에 1을 더한 값이다. 
– 빈 리스트의 length는 0이다. 
• Null? – 인자가 빈인자인지 판단. 
(define (length items) 
(if (null? items) 
0 
(+ 1 (length (cdr items))))) 
(define odds (list 1 3 5 7)) 
(length odds) 
4 
----------------------------------------------- 
(define (length items) 
(define (length-iter a count) 
(if (null? a) 
count 
(length-iter (cdr a) (+ 1 count)))) 
(length-iter items 0)) 
(define odds (list 1 3 5 7)) 
(length odds)
리스트 연산 
• ‘리스트 구조를 cdr로 풀어 헤치면서, 
이를 cons로 되묶어서 새로운 리스트 
를 만드는 방법’ 
• Append 프로시져 – 두 리스트를 인자 
로 받아 모든 원소를 한데 엮어 새 리 
스트를 만듬. 
• Append 규칙 
– List1이 빈 리스트면, 결과는 list2임. 
– 그렇지 않으면, list1의 cdr와 list2를 
append한 다음 , 그 결과에 list1의 
car를 cons 한 리스트를 만듬. 
(define squares (list 1 2 3 4)) 
(define odds (list 6 7 8 9)) 
(define (append list1 list2) 
(if (null? list1) 
list2 
(cons (car list1) 
(append (cdr list1) list2)))) 
(append squares odds) 
- 1 2 3 4 6 7 8 9
리스트 매핑(Mapping) 
• 리스트 연산에서 계산 방법을 요 
약해서 차수높은 프로시져 
(Higher-Order Procedure )를 
만든것이 Map. 
• Map – 프로시져 하나와 리스트를 
인자로 받아, 리스트 원소 
마다 똑같은 프로시져를 
적용한 결과를 묶은 
리스트를 반환. 
(define (scale-list items factor) 
(if (null? items) 
null 
(cons (* (car items) factor) 
(scale-list (cdr items) 
factor)))) 
(scale-list (list 1 2 3 4 5) 10) 
(10 20 30 40 50) 
--------------------------------- 
(define items1 (list 1 2 3 4 5)) 
(define factor1 10) 
(define (scale-list1 items factor) 
(map (lambda (x) (* x factor)) 
items)) 
(scale-list1 items1 factor1)
2.2.2 계층 구조 
• 차례열을 원소로하는 차례열을 
나타낼수 있음. 
(cons (list 1 2) (list 3 4)) 
• 차례열을 원소로 가지는 차례 
열을 나무(Tree) 꼴로 펼쳐 나 
타낼수있음.
Count-leaves 프로시져 
• Count-leaves 프로시져 - 재귀 처리 
로 나무 가지를 순회하여 나뭇잎의 
카운터를 계산. 
• Count-leaves 규칙 
– 리스트 x의 length는 x의 cdr의 
length에 1을 더한 값이다. 
– 빈 리스트의 length는 0이다. 
• Pair 프로시져 – 인자로 받은 값이 쌍인지 
판단. 
#lang scheme ;added 
(define x (cons (list 1 2) (list 3 4))) 
(length (list x x)) 
- 2 
(count-leaves x) 
- 4 
;--------------------------------------------- 
(define (count-leaves x) 
(cond ((null? x) 0) 
((not (pair? x)) 1) 
(else (+ (count-leaves (car x)) 
(count-leaves (cdr x))))))
나무 매핑 
• Map과 재귀 처리 방식을 한데 엮 
어 나무꼴 데이터를 효과적으로 
다룰 수 있음. 
• scale-tree 프로시져 – 곱할 수와 
나무를 인자로 받아, 모든 나뭇잎 
에 곱수가 곱해진 나무를 반환. 
• 다른 방법은 나무를 부분 나무의 
차례열로 보고, map을 사용. 
(define (scale-tree tree factor) 
(cond ((null? tree) null) 
((not (pair? tree)) (* tree factor)) 
(else (cons (scale-tree (car tree) factor) 
(scale-tree (cdr tree) factor))))) 
(scale-tree (list 1 (list 2 (list 3 4) 5) (list 6 7)) 10) 
------------------------------------------------------- 
(define tempTree (list 1 (list 2 (list 3 4) 5) (list 6 7))) 
(define (scale-tree tree factor) 
(map (lambda (sub-tree1) 
(if (pair? sub-tree1) 
(scale-tree sub-tree1 factor) 
(* sub-tree1 factor))) 
tree)) 
(scale-tree tempTree 10) 
;(10 (20 (30 40) 50) (60 70))
2.2.3 공통 인터페이스로써 차례열의 쓰임새 
• 나무꼴 데이터를 인자로 
받아서 잎사귀 가운데 홀수인 
것만 제곱한 다음에 이것을 모두 
더한 값을 반환 
------------------------------------ 
• N보다 작거나 N과 같은 
정수 K에 대하여 피보나치 수열 
Fib(k) 값을 구한 후 짝수만 
모아서 리스트로 묶어내는 
프로시져 
(define (square x) (* x x)) 
(define (sum-odd-squares tree) 
(cond ((null? tree) 0) 
((not (pair? tree)) 
(if (odd? tree) (square tree) 0)) 
(else (+ (sum-odd-squares (car tree)) 
(sum-odd-squares (cdr tree)))))) 
---------------------------------------------------- 
(define (even-fibs n) 
(define (next k) 
(if (> k n) 
null 
(let ((f (fib (k)))) 
(if (even? f) 
(cons f (next (+ k 1))) 
(next (+ k 1)))))) 
(next 0))
• 처리 과정이 비슷함. 
• 그러나 두 프로시져는 신호가 흘러가는 구조를 갖추지 못하였음. 
• 따라서 두 프로시저 정의에서는 신호 흐름 방식의 단계별 처리 과정 
이 확실히 대응하는 부분을 찾기 힘듬.
차례열 연산 
• 계산 단계에서 다음 계산 단계로 흘러가는 
신호를 리스트로 나타내면, 모든 단계별 
처리 과정을 리스트 연산이 가능함. 
• 모듈 방식으로 독립된 부품을 짜 맞추듯이 
프로그램을 설계
Map 
• (map square (list 1 2 3 4 5)) 
• (1 4 9 16 25)
Filter 
(define (filter predicate sequence) 
(cond ((null? sequence) nil) 
((predicate (car sequence)) 
(cons (car sequence) 
(filter predicate (cdr sequence)))) 
(else (filter predicate (cdr sequence))))) 
(filter odd? (list 1 2 3 4 5)) 
(1 3 5)
Accumulate 
(define (accumulate op initial sequence) 
(if (null? sequence) 
initial 
(op (car sequence) 
(accumulate op initial (cdr sequence))))) 
(accumulate + 0 (list 1 2 3 4 5)) 
15 
(accumulate * 1 (list 1 2 3 4 5)) 
120
Enumerate 
(define (enumerate-tree tree) 
(cond ((null? tree) nil) 
((not (pair? tree)) (list tree)) 
(else (append 
(enumerate-tree (car tree)) 
(enumerate-tree (cdr tree)))))) 
(enumerate-tree (list 1 (list 2 (list 3 4)) 5)) 
(1 2 3 4 5) 
(define (enumerate-interval low high) 
(if (> low high) 
nil 
(cons low (enumerate-interval (+ low 1) 
high)))) 
(enumerate-interval 2 7) 
(2 3 4 5 6 7)
모듈 조합 
(define (sum-odd-squares tree) 
(accumulate + 
0 
(map square 
(filter odd? 
(enumerate-tree tree))))) 
---------------------------------------------------------------------------- 
(define (even-fibs n) 
(accumulate cons 
nil 
(filter even? 
(map fib 
(enumerate-interval 0 n)))))
겹친 매핑 
• 차례열 패러다임의 쓰임새를 넓혀서, 겹친 루프를 써서 나타낼 수 
있는 계산 문제를 표현 
• 양의 정수 n, I, j가 있을때, 1 <= j < I <= n 만족하고 I + j 의 값이 
소수가 되는 i와 j의 모든 순서 쌍을 구하는 문제 
• N = 6 일 경우.
• Enumerate 
– n보다 작거나 같은 양의 
정수로 이루어진 모든 순서 
쌍을 차례열로 묶어냄 
• Filter 
– 그 가운데 그 합이 소수인 
쌍들만 거르개로 고름. 
• Map 
– 골라낸 쌍(I,j)에 대해 트리 
플(I,j, i+j)를 만듬. 
• Accumulate 
(accumulate append 
nil 
(map (lambda (i) 
(map (lambda ( j) (list i j)) 
(enumerate-interval 1 (- i 1)))) 
(enumerate-interval 1 n))) 
(define (flatmap proc seq) 
(accumulate append nil (map proc seq))) 
---------------------------------------------------------- 
(define (prime-sum? pair) 
(prime? (+ (car pair) (cadr pair)))) 
---------------------------------------------------------- 
(define (make-pair-sum pair) 
(list (car pair) (cadr pair) 
(+ (car pair) (cadr pair))))
(define (prime-sum-pairs n) 
(map make-pair-sum 
(filter prime-sum? 
(flatmap 
(lambda (i) 
(map (lambda ( j) (list i j)) 
(enumerate-interval 1 (- i 1)))) 
(enumerate-interval 1 n)))))
(define (enumerate-interval low high) 
(if (> low high) 
null 
(cons low (enumerate-interval (+ low 1) high)))) 
;------------------------------------------------ 
(define (accumulate append null) 
((map (lambda (i) 
(map (lambda (j) (list i j)) 
(enumerate-interval 1 (- i 1)))) 
(enumerate-interval 1 n)))) 
(define (flatmap proc seq) 
(accumulate append null (map proc seq))) 
;---------------------------------------------------------- 
(define (square x) (* x x)) 
(define (find-divisor n test-divisor) 
(cond ((> (square test-divisor) n) n) 
((divides? test-divisor n) test-divisor) 
(else (find-divisor n (+ test-divisor 1))))) 
(define (divides? a b) (= (remainder b a) 0)) 
(define (smallest-divisor n) (find-divisor n 2)) 
(define (prime? n) 
(= n (smallest-divisor n))) 
(define (prime-sum? pair) 
(prime? (+ (car pair) (cadr pair)))) 
;---------------------------------------------------------- 
(define (make-pair-sum pair) 
(list (car pair) (cadr pair) 
(+ (car pair) (cadr pair)))) 
;---------------------------------------------------------- 
(define (prime-sum-pairs n) 
(map make-pair-sum 
(filter prime-sum? 
(flatmap (lambda (i) 
(map (lambda (j) (list i j)) 
(enumerate-interval 1 (- i 1)))) 
(enumerate-interval 1 n)))))
2.2.4 그림 언어 
• 데이터 요약과 닫힘 성질, 아울러 차수 높은 
프로시저가 프로그램 설계에 미치는 힘을 
살펴보기 위해 그림을 그리는데 쓰는 간단한 
그림 언어를 만들어 보자. 
• 그림언어는 페인터라는 한가지 요소만 갖춤.
• Wave 라는 기본 페인터를 써서 그린 그림.
• Rogers 페인터 사용.
(define wave2 (beside wave (flip-vert wave))) 
(define wave4 (below wave2 wave2))
(define (flipped-pairs painter) 
(let ((painter2 (beside painter (flip-vert painter)))) 
(below painter2 painter2))) 
(define wave4 (flipped-pairs wave))
(define (right-split painter n) 
(if (= n 0) 
painter 
(let ((smaller (right-split painter (- n 1)))) 
(beside painter (below smaller 
smaller))))) 
------------------------------------------------- 
(define (corner-split painter n) 
(if (= n 0) 
painter 
(let ((up (up-split painter (- n 1))) 
(right (right-split painter (- n 1)))) 
(let ((top-left (beside up up)) 
(bottom-right (below right right)) 
(corner (corner-split painter (- n 
1)))) 
(beside (below painter top-left) 
(below bottom-right corner))))))
그림틀 
Origin(Frame) + x Edge1(Frame) + y Edge2(Frame) 
(define (frame-coord-map frame) 
(lambda (v) 
(add-vect 
(origin-frame frame) 
(add-vect (scale-vect (xcor-vect v) 
(edge1-frame frame)) 
(scale-vect (ycor-vect v) 
(edge2-frame 
frame)))))) 
((frame-coord-map a-frame) (make-vect 0 
0)) 
(origin-frame a-frame)
페인터 
• 페인터 프로시져는 그림틀을 인자로 받아 
서, 그 틀에 맞춘 그림을 그림. 
(define (segments->painter segment-list) 
(lambda (frame) 
(for-each 
(lambda (segment) 
(draw-line 
((frame-coord-map frame) (start-segment segment)) 
((frame-coord-map frame) (end-segment segment)))) 
segment-list)))
단단하게 설계할 때 쓰는 언어 
• 다층 설계 – 단계별로 여러 언어를 쌓아올 
려 복잡한 시스템을 층층이 짜맞추어 가는 
방법 
• 다층 설계 방식은 프로그램을 “튼튼하게” 
짜는데 큰 도움을 줌.
Referance 
• 컴퓨터 프로그램의 구조와 해석 2/E 
– 헤럴드에빌슨, 제럴드 제이 서스먼, 줄리 서스먼 지음. 인사이트.

Sicp 2.2 계층 구조 데이터와 닫힘 성질

  • 1.
    2.2 계층 구조데이터와 닫힘 성질 Structure and Interpretation of Computer Programs aceigy6322@gmail.com 2014.10.18
  • 2.
    상자와 화살표 쌍을나타내기 닫힘 성질로 계층 구조 표현 가능 - 차례열(Sequence) - 나무(Tree) - 그림 언어(Graphic)
  • 3.
    2.2.1 차례열(Sequence) 표현방법 (cons ⟨a1⟩ (cons ⟨a2⟩ (cons : : : (cons ⟨an⟩ nil): : :))) (list ⟨a1⟩ ⟨a2⟩ : : : ⟨an⟩) 리스트 - Cons를 겹쳐 만든 쌍의 차례열 (define one-through-four (list 1 2 3 4)) • one-through-four - (1 2 3 4) • (car one-through-four) - 1 • (cdr one-through-four) - (2 3 4) • (car (cdr one-through-four)) - 2 • (cons 10 one-through-four) - (10 1 2 3 4)
  • 4.
    리스트 연산 •‘cdr연산을 가지고 흝어 내려가는’ 프 로그램 기법으로 리스트 연산을 만 듬. • List-ref 프로시져 - 리스트와 수 N 을 인자로 받아서, 그 리스트의 n번 째 원소를 내놓음. • List-ref 규칙 – N = 0이면, list-ref의 값은 리스트의 car 이다. – 그렇지 않으면, list-ref는 리스트의 cdr에서 n-1번째 원소다. (define (list-ref items n) (if (= n 0) (car items) (list-ref (cdr items) (- n 1)))) (define squares (list 1 4 9 16 25)) (list-ref squares 3) 16
  • 5.
    리스트 연산 •length 프로시져 - 리스트를 인자로 받아 리스트의 원소가 몇 개인지 찾 음. • length 규칙 – 리스트의 length는 그 리스트의 cdr 의 length에 1을 더한 값이다. – 빈 리스트의 length는 0이다. • Null? – 인자가 빈인자인지 판단. (define (length items) (if (null? items) 0 (+ 1 (length (cdr items))))) (define odds (list 1 3 5 7)) (length odds) 4 ----------------------------------------------- (define (length items) (define (length-iter a count) (if (null? a) count (length-iter (cdr a) (+ 1 count)))) (length-iter items 0)) (define odds (list 1 3 5 7)) (length odds)
  • 6.
    리스트 연산 •‘리스트 구조를 cdr로 풀어 헤치면서, 이를 cons로 되묶어서 새로운 리스트 를 만드는 방법’ • Append 프로시져 – 두 리스트를 인자 로 받아 모든 원소를 한데 엮어 새 리 스트를 만듬. • Append 규칙 – List1이 빈 리스트면, 결과는 list2임. – 그렇지 않으면, list1의 cdr와 list2를 append한 다음 , 그 결과에 list1의 car를 cons 한 리스트를 만듬. (define squares (list 1 2 3 4)) (define odds (list 6 7 8 9)) (define (append list1 list2) (if (null? list1) list2 (cons (car list1) (append (cdr list1) list2)))) (append squares odds) - 1 2 3 4 6 7 8 9
  • 7.
    리스트 매핑(Mapping) •리스트 연산에서 계산 방법을 요 약해서 차수높은 프로시져 (Higher-Order Procedure )를 만든것이 Map. • Map – 프로시져 하나와 리스트를 인자로 받아, 리스트 원소 마다 똑같은 프로시져를 적용한 결과를 묶은 리스트를 반환. (define (scale-list items factor) (if (null? items) null (cons (* (car items) factor) (scale-list (cdr items) factor)))) (scale-list (list 1 2 3 4 5) 10) (10 20 30 40 50) --------------------------------- (define items1 (list 1 2 3 4 5)) (define factor1 10) (define (scale-list1 items factor) (map (lambda (x) (* x factor)) items)) (scale-list1 items1 factor1)
  • 8.
    2.2.2 계층 구조 • 차례열을 원소로하는 차례열을 나타낼수 있음. (cons (list 1 2) (list 3 4)) • 차례열을 원소로 가지는 차례 열을 나무(Tree) 꼴로 펼쳐 나 타낼수있음.
  • 9.
    Count-leaves 프로시져 •Count-leaves 프로시져 - 재귀 처리 로 나무 가지를 순회하여 나뭇잎의 카운터를 계산. • Count-leaves 규칙 – 리스트 x의 length는 x의 cdr의 length에 1을 더한 값이다. – 빈 리스트의 length는 0이다. • Pair 프로시져 – 인자로 받은 값이 쌍인지 판단. #lang scheme ;added (define x (cons (list 1 2) (list 3 4))) (length (list x x)) - 2 (count-leaves x) - 4 ;--------------------------------------------- (define (count-leaves x) (cond ((null? x) 0) ((not (pair? x)) 1) (else (+ (count-leaves (car x)) (count-leaves (cdr x))))))
  • 10.
    나무 매핑 •Map과 재귀 처리 방식을 한데 엮 어 나무꼴 데이터를 효과적으로 다룰 수 있음. • scale-tree 프로시져 – 곱할 수와 나무를 인자로 받아, 모든 나뭇잎 에 곱수가 곱해진 나무를 반환. • 다른 방법은 나무를 부분 나무의 차례열로 보고, map을 사용. (define (scale-tree tree factor) (cond ((null? tree) null) ((not (pair? tree)) (* tree factor)) (else (cons (scale-tree (car tree) factor) (scale-tree (cdr tree) factor))))) (scale-tree (list 1 (list 2 (list 3 4) 5) (list 6 7)) 10) ------------------------------------------------------- (define tempTree (list 1 (list 2 (list 3 4) 5) (list 6 7))) (define (scale-tree tree factor) (map (lambda (sub-tree1) (if (pair? sub-tree1) (scale-tree sub-tree1 factor) (* sub-tree1 factor))) tree)) (scale-tree tempTree 10) ;(10 (20 (30 40) 50) (60 70))
  • 11.
    2.2.3 공통 인터페이스로써차례열의 쓰임새 • 나무꼴 데이터를 인자로 받아서 잎사귀 가운데 홀수인 것만 제곱한 다음에 이것을 모두 더한 값을 반환 ------------------------------------ • N보다 작거나 N과 같은 정수 K에 대하여 피보나치 수열 Fib(k) 값을 구한 후 짝수만 모아서 리스트로 묶어내는 프로시져 (define (square x) (* x x)) (define (sum-odd-squares tree) (cond ((null? tree) 0) ((not (pair? tree)) (if (odd? tree) (square tree) 0)) (else (+ (sum-odd-squares (car tree)) (sum-odd-squares (cdr tree)))))) ---------------------------------------------------- (define (even-fibs n) (define (next k) (if (> k n) null (let ((f (fib (k)))) (if (even? f) (cons f (next (+ k 1))) (next (+ k 1)))))) (next 0))
  • 12.
    • 처리 과정이비슷함. • 그러나 두 프로시져는 신호가 흘러가는 구조를 갖추지 못하였음. • 따라서 두 프로시저 정의에서는 신호 흐름 방식의 단계별 처리 과정 이 확실히 대응하는 부분을 찾기 힘듬.
  • 13.
    차례열 연산 •계산 단계에서 다음 계산 단계로 흘러가는 신호를 리스트로 나타내면, 모든 단계별 처리 과정을 리스트 연산이 가능함. • 모듈 방식으로 독립된 부품을 짜 맞추듯이 프로그램을 설계
  • 14.
    Map • (mapsquare (list 1 2 3 4 5)) • (1 4 9 16 25)
  • 15.
    Filter (define (filterpredicate sequence) (cond ((null? sequence) nil) ((predicate (car sequence)) (cons (car sequence) (filter predicate (cdr sequence)))) (else (filter predicate (cdr sequence))))) (filter odd? (list 1 2 3 4 5)) (1 3 5)
  • 16.
    Accumulate (define (accumulateop initial sequence) (if (null? sequence) initial (op (car sequence) (accumulate op initial (cdr sequence))))) (accumulate + 0 (list 1 2 3 4 5)) 15 (accumulate * 1 (list 1 2 3 4 5)) 120
  • 17.
    Enumerate (define (enumerate-treetree) (cond ((null? tree) nil) ((not (pair? tree)) (list tree)) (else (append (enumerate-tree (car tree)) (enumerate-tree (cdr tree)))))) (enumerate-tree (list 1 (list 2 (list 3 4)) 5)) (1 2 3 4 5) (define (enumerate-interval low high) (if (> low high) nil (cons low (enumerate-interval (+ low 1) high)))) (enumerate-interval 2 7) (2 3 4 5 6 7)
  • 18.
    모듈 조합 (define(sum-odd-squares tree) (accumulate + 0 (map square (filter odd? (enumerate-tree tree))))) ---------------------------------------------------------------------------- (define (even-fibs n) (accumulate cons nil (filter even? (map fib (enumerate-interval 0 n)))))
  • 19.
    겹친 매핑 •차례열 패러다임의 쓰임새를 넓혀서, 겹친 루프를 써서 나타낼 수 있는 계산 문제를 표현 • 양의 정수 n, I, j가 있을때, 1 <= j < I <= n 만족하고 I + j 의 값이 소수가 되는 i와 j의 모든 순서 쌍을 구하는 문제 • N = 6 일 경우.
  • 20.
    • Enumerate –n보다 작거나 같은 양의 정수로 이루어진 모든 순서 쌍을 차례열로 묶어냄 • Filter – 그 가운데 그 합이 소수인 쌍들만 거르개로 고름. • Map – 골라낸 쌍(I,j)에 대해 트리 플(I,j, i+j)를 만듬. • Accumulate (accumulate append nil (map (lambda (i) (map (lambda ( j) (list i j)) (enumerate-interval 1 (- i 1)))) (enumerate-interval 1 n))) (define (flatmap proc seq) (accumulate append nil (map proc seq))) ---------------------------------------------------------- (define (prime-sum? pair) (prime? (+ (car pair) (cadr pair)))) ---------------------------------------------------------- (define (make-pair-sum pair) (list (car pair) (cadr pair) (+ (car pair) (cadr pair))))
  • 21.
    (define (prime-sum-pairs n) (map make-pair-sum (filter prime-sum? (flatmap (lambda (i) (map (lambda ( j) (list i j)) (enumerate-interval 1 (- i 1)))) (enumerate-interval 1 n)))))
  • 22.
    (define (enumerate-interval lowhigh) (if (> low high) null (cons low (enumerate-interval (+ low 1) high)))) ;------------------------------------------------ (define (accumulate append null) ((map (lambda (i) (map (lambda (j) (list i j)) (enumerate-interval 1 (- i 1)))) (enumerate-interval 1 n)))) (define (flatmap proc seq) (accumulate append null (map proc seq))) ;---------------------------------------------------------- (define (square x) (* x x)) (define (find-divisor n test-divisor) (cond ((> (square test-divisor) n) n) ((divides? test-divisor n) test-divisor) (else (find-divisor n (+ test-divisor 1))))) (define (divides? a b) (= (remainder b a) 0)) (define (smallest-divisor n) (find-divisor n 2)) (define (prime? n) (= n (smallest-divisor n))) (define (prime-sum? pair) (prime? (+ (car pair) (cadr pair)))) ;---------------------------------------------------------- (define (make-pair-sum pair) (list (car pair) (cadr pair) (+ (car pair) (cadr pair)))) ;---------------------------------------------------------- (define (prime-sum-pairs n) (map make-pair-sum (filter prime-sum? (flatmap (lambda (i) (map (lambda (j) (list i j)) (enumerate-interval 1 (- i 1)))) (enumerate-interval 1 n)))))
  • 23.
    2.2.4 그림 언어 • 데이터 요약과 닫힘 성질, 아울러 차수 높은 프로시저가 프로그램 설계에 미치는 힘을 살펴보기 위해 그림을 그리는데 쓰는 간단한 그림 언어를 만들어 보자. • 그림언어는 페인터라는 한가지 요소만 갖춤.
  • 24.
    • Wave 라는기본 페인터를 써서 그린 그림.
  • 25.
  • 26.
    (define wave2 (besidewave (flip-vert wave))) (define wave4 (below wave2 wave2))
  • 27.
    (define (flipped-pairs painter) (let ((painter2 (beside painter (flip-vert painter)))) (below painter2 painter2))) (define wave4 (flipped-pairs wave))
  • 28.
    (define (right-split paintern) (if (= n 0) painter (let ((smaller (right-split painter (- n 1)))) (beside painter (below smaller smaller))))) ------------------------------------------------- (define (corner-split painter n) (if (= n 0) painter (let ((up (up-split painter (- n 1))) (right (right-split painter (- n 1)))) (let ((top-left (beside up up)) (bottom-right (below right right)) (corner (corner-split painter (- n 1)))) (beside (below painter top-left) (below bottom-right corner))))))
  • 29.
    그림틀 Origin(Frame) +x Edge1(Frame) + y Edge2(Frame) (define (frame-coord-map frame) (lambda (v) (add-vect (origin-frame frame) (add-vect (scale-vect (xcor-vect v) (edge1-frame frame)) (scale-vect (ycor-vect v) (edge2-frame frame)))))) ((frame-coord-map a-frame) (make-vect 0 0)) (origin-frame a-frame)
  • 30.
    페인터 • 페인터프로시져는 그림틀을 인자로 받아 서, 그 틀에 맞춘 그림을 그림. (define (segments->painter segment-list) (lambda (frame) (for-each (lambda (segment) (draw-line ((frame-coord-map frame) (start-segment segment)) ((frame-coord-map frame) (end-segment segment)))) segment-list)))
  • 31.
    단단하게 설계할 때쓰는 언어 • 다층 설계 – 단계별로 여러 언어를 쌓아올 려 복잡한 시스템을 층층이 짜맞추어 가는 방법 • 다층 설계 방식은 프로그램을 “튼튼하게” 짜는데 큰 도움을 줌.
  • 32.
    Referance • 컴퓨터프로그램의 구조와 해석 2/E – 헤럴드에빌슨, 제럴드 제이 서스먼, 줄리 서스먼 지음. 인사이트.