각 단계에 이름을 붙이고 흐름을 조합한다.
열거와 고르기와 바꾸기와 누적을 나누면 하나의 데이터 질문을 따로 이해하고 바꿀 수 있는 단계들로 분리할 수 있습니다.
생각해 볼 질문
수열 파이프라인은 중첩된 재귀를 어떻게 이름 붙은 단계로 바꿀까요?
- 유한한 입력 구간 열거하기
- 술어로 값을 고르고 프로시저로 바꾸기
- 수열을 값 하나로 누적하기
- 마지막 값을 예상하기 전에 중간 수열의 모양 읽기
enumerate-interval은 시작 수열을 만듭니다. filter는 odd?가 받아들이는 값만 남기고 map은 남은 값을 제곱으로 바꿉니다. 프로시저 하나마다 결정 하나만 맡습니다.
accumulate는 +와 초기값 0으로 바뀐 수열을 값 하나에 모읍니다. 전체 프로그램은 여전히 재귀하지만 제어가 하나의 특수 목적 프로시저에 뒤섞이지 않고 다시 쓸 수 있는 단계에 나뉘어 있습니다.
(begin
(define (enumerate-interval low high)
(if (> low high)
'()
(cons low (enumerate-interval (+ low 1) high))))
(define (filter predicate items)
(cond ((null? items) '())
((predicate (car items))
(cons (car items) (filter predicate (cdr items))))
(else (filter predicate (cdr items)))))
(define (map procedure items)
(if (null? items)
'()
(cons (procedure (car items))
(map procedure (cdr items)))))
(define (accumulate operation initial items)
(if (null? items)
initial
(operation (car items)
(accumulate operation initial (cdr items)))))
(define (square value) (* value value))
(accumulate + 0
(map square
(filter odd? (enumerate-interval 1 8)))))리스펙스 학습용 런타임리스펙스 SICP 프로필 1.0.0
리스펙스 SICP 런타임 불러오는 중
리스펙스 · SICP 코드UTF-8 802 / 1,048,576바이트
예제
결과—
- 출력
- —
- 값
- —
- 진단
- —
보이는 실행 흐름0 / 0 개의 실행 이벤트
프로그램은 1² + 3² + 5² + 7²의 값인 84를 반환합니다.
구간 리스트가 filter로 들어가는 과정을 따라간 뒤 짧아진 홀수 리스트와 accumulate가 받는 제곱 리스트를 비교하세요. 마지막 덧셈은 앞 단계들이 중간 모양을 만든 뒤 일어납니다. 이 실행 흐름은 선택한 이번 실행만 설명하며 리스펙스 바우치나 권한이 아닙니다.
힌트를 보기 전에 프로그램을 바꿔 보세요.
odd?를 even?로 바꾼 다음 accumulate의 +와 0 대신 cons와 '()를 사용하세요. 나오는 리스트와 순서를 예상해 보세요.
힌트 하나 보기
마지막 단계는 인수 두 개를 받는 프로시저와 그에 맞는 초기값을 받을 수 있습니다.