차수 높은 프로시저를 만들어 사용하면, 간추려 만든 프로시저의 쓰임새를 훨씬 늘릴 수 있다. 다시 말해, 수뿐 아니라 함수까지 인자로 받을 수 있기 때문에, 계산하는 방법만 도려내어 프로시저로 간추릴 수 있다.
1.1.7절에서 살펴본 제곱근 프로시저를 고정점 찾는 방법으로 나타내보자. (고정점이란 f(x) = x 를 만족하는 x이다.)
수 x의 제곱근이란, y^2 = x 를 만족하는 y의 값과 같다. 이를 달리 나타내면, y = x/y가 되고, y -> x/y 함수의 고정점을 찾는 문제와 같다. (x/y = y -> x = y^2)
고정점 찾기 프로시저를 fixed-point라 하면 프로시저는 다음과 같이 나타낼 수 있다.
(define (sqrt x)
(fixed-point (lambda (y) (/ x y))
1.0))
fixed-point 프로시저는 f(x), f(f(x)), f(f(f(x))) ... 를 반복하며 x의 값이 크게 변하지 않는 점을 고정점으로 하는 프로시저이다.
그러나, 위 sqrt 프로시저는 고정점 주위값을 왔다갔다만 반복할 뿐 값이 도출되지 않는다.
위와 같은 상황에서 y -> x/y로 사용하는 것이 아니라, 두 값의 중간값을 사용하여 y -> (y + x/y)/2 로 변형하여 값을 도출할 수 있다.
앞서 살펴보았듯이 프로시저를 인자로 받아 쓸 수 있을 때 표현력이 크게 늘어났다.
마찬가지로, 프로시저를 프로시저의 결과값으로 돌려줄 수 있으면 표현력이 더 늘어난다는 사실을 확인해보자.
1.3.3 절 마지막에 살펴본 두 값의 평균을 사용해 다음 값을 도출하는 프로시저를 프로시저를 만드는 프로시저를 사용해 나타내보자.
(define (average-damp f)
(lambda (x) (average x (f x))))
위 프로시저를 사용하면 인자로 넘어온 f 프로시저에 대해 x 값을 인자로 받아 x와 f(x)의 평균을 구해주는 프로시저를 얻을 수 있다.
위 프로시저를 활용하여 1.3.3절의 마지막 문제를 표현해보자.
(define (sqrt x)
(fixed-point (average-damp (lambda (x) (/ x y)))
1.0))
위 프로시저는 단순히 1.3.3 절의 lambda 식에 (/ x y) 대신 (average x (/ x y)) 를 넣은 것과 다르지 않다.
그러나, 단순히 해당 함수를 사용한 것이 아니라, 평균값을 사용하여 고정점을 찾는 프로시저라는 것을 더 확실하게 드러내고 있다.
1.3절에서는 차수 높은 프로시저를 활용하면 얼마나 표현력을 끌어올릴 수 있는지 살펴보았다.
프로그래머는 간추릴 것을 찾아내어 더 수준 높은 표현 수단을 만들어내려 애써야 한다.
요약할 것이 없을 때까지 요약하라는 말이 아니다.
다른 문제 플이에도 다시 쓸 수 있도록 일반적인 표현 수단을 만들려고 애쓰는 버릇이 중요하다.
추가. 일등급(first-class)이란?
일등급의 권리와 특징
변수의 값이 될 수 있다. 즉, 이름이 붙을 수 있다.
프로시저의 인자로 쓸 수 있다.
프로시저의 결과로 만들어질 수 있다.
데이터 구조 속에 집어넣을 수 있다.
Lisp 에서 프로시저는 일등급 프로시저이다.
일등급 프로시저를 구현하기 위해서는 여러 제약이 따라 붙는데, 가장 큰 제약이 메모리적인 측면이다. 4.1절에서 자세하게 다룬다.