오상우
오상우

Categories

  • lisp
  • scheme
  • sicp

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)))