list를 사용하면 좋은 점 한 가지는, 공통의 인터페이스가 생김으로 인해 프로세스를 패턴화 할 수 있다는 점이다.
대표적인 패턴으로 enumerator, filter, map, accumulator 등이 있다.
tree 자료구조에서 리프 값들 중, 홀수 값을 제곱하여 더하는 프로시저는 다음과 같이 정의할 수 있다.
(define (sum-odd-squares tree)
(accumulator +
0
(map square
(filter odd?
(enumerate-tree tree)))))
연습문제 2.33
accumulator를 이용하여 리스트 기본 연산을 정의하여라.
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op initial (cdr sequence)))))
(define (map p sequence)
(accumulate (lambda (x y) (cons (p x) y)) () sequence))
(map square (list 1 2 3 4))
(define (append seq1 seq2)
(accumulate cons seq2 seq1))
(append (list 1 2 3) (list 4 5 6))
(define (length sequence)
(accumulate (lambda (x y) (+ 1 y)) 0 sequence))
(length (list 1 2 3))
연습문제 2.34
호너의 규칙을 사용해 다항식의 값을 구하는 프로시저를 작성하여라.
(define (horner-eval x coefficient-sequence)
(accumulate (lambda (this-coeff higher-terms)
(+ this-coeff
(* higher-terms x)))
0
coefficient-sequence))
(horner-eval 2 (list 1 3 0 5 0 1))
; 79
연습문제 2.35
accumulate를 사용해 count-leaves 프로시저를 다시 정의해 보라.
이 문제가 조금 헷갈렸는데, 재귀적으로 문제를 해결할 때 서브 문제는 이미 해결됐다고 생각하면 된다는 점을 이용해서 쉽게 풀 수 있다.
(define (count-leaves t)
(accumulate +
0
(map (lambda (subt)
(if (not (pair? subt))
1
(count-leaves subt)))
t)))