프로시저는 다음 프로시저를 만들어 돌려줄 수 있다.
합성과 반복과 평균 감쇠는 동작을 데이터처럼 다룹니다. 한 프로시저가 다른 프로시저를 받아 나중에 이름 붙이고 전달하고 적용할 수 있는 새 변환을 반환합니다.
프로시저 호출의 결과가 또 다른 프로시저라면 어떤 새로운 구성이 가능해질까요?
- lambda 식을 다른 프로시저가 반환하는 프로시저 값으로 읽기
- 변환을 만드는 시점과 그 변환을 적용하는 시점 구분하기
- 소스에서 적용 순서가 드러나도록 프로시저 합성하기
- 동작 본문을 복사하지 않고 반복되는 변환 만들기
- 평균 감쇠를 프로시저를 만드는 변환으로 이해하기
compose는 프로시저 값 두 개를 받고 새로운 프로시저를 반환합니다. compose를 호출하는 순간에는 아직 어떤 수도 제곱하거나 증가시키지 않습니다. f와 g를 기억하는 변환을 만들 뿐입니다. 나중에 x를 주어 적용하면 g를 먼저 실행하고 그 결과에 f를 적용합니다. repeated도 같은 생각을 재귀적으로 사용하여 횟수가 0이면 항등 변환을, 더 큰 횟수에서는 합성을 하나 더 얹은 변환을 돌려줍니다.
average-damp도 프로시저를 반환합니다. 반환된 변환은 원래 f를 x에 적용한 값과 x의 평균을 계산합니다. 제곱근 변환 y ↦ 16/y에 추측값 2를 넣으면 5가 되고 고정점인 4를 넣으면 그대로 4가 됩니다. 프로시저 생성자는 재사용할 방법을 가지고 있고, 전달된 f가 실제로 바꿀 동작을 결정합니다.
(begin
(define (compose f g)
(lambda (x) (f (g x))))
(define (repeated f count)
(if (= count 0)
(lambda (x) x)
(compose f (repeated f (- count 1)))))
(define (increment x) (+ x 1))
(define (square x) (* x x))
(list ((compose square increment) 6)
((compose increment square) 6)
((repeated increment 5) 10)))- 출력
- —
- 값
- —
- 진단
- —
합성 프로그램은 (49 37 15)를 반환합니다. 평균 감쇠 프로그램은 (5 4 21)을 반환합니다.
반환할 프로시저를 만드는 호출과 그 프로시저를 나중에 적용하는 호출을 나누어 보세요. 합성 예제에서는 증가한 뒤 제곱하는 경우와 제곱한 뒤 증가하는 경우를 비교합니다. 평균 감쇠 예제에서는 평균을 만들기 전에 포획한 f가 호출되는 곳을 찾으세요. 실행 흐름은 이 유한한 적용을 보여 줄 뿐 두 변환의 일반적인 동등성을 증명하지는 않습니다.
힌트를 보기 전에 프로그램을 바꿔 보세요.
compose만 사용해 twice를 정의하고 ((twice increment) 10)과 ((twice square) 3)을 함께 반환하세요. 실행하기 전에 두 값을 예상해 보세요.
힌트 하나 보기
twice는 f를 자기 자신과 합성한 것과 같은 프로시저를 반환해야 합니다. 예상값은 12와 81입니다.