이 또한 식이 어떤 타입이냐에 따라 할 일을 나누어 맡기는 프로그램이라 볼 수 있다. 이 경우에는 (+ 같은) 대수식의 연산 기호가 데이터의 '타입 흐름표’가 되고, deriv는 그 데이터를 적용할 연산이 된다. 이 프로그램을 데이터 중심 방식으로 바꾸려면 위 미분 프로시저를 다음과 같이 고쳐 쓰면 된다.
a. 위에서 한 일이 무엇인지 설명해 보라. number?나 variable?같은 술어 프로시저를 모조리 데이터 중심 방식으로 다루지 못하는 이유는 무엇인가?
b. 덧셈과 곱셈식을 미분하는 프로시저를 짜라. 그런 다음, 그 프로시저들을 위 프로그램에서 쓰는 표에 집어넣는데 필요한 코드를 짜라.
c. (연습문제 2.56에서 나온 것처럼) 지수 식을 미분하는 것과 같이, 새로 보태고 싶은 규칙을 하나 골라 여기서 만든 데이터 중심 시스템에 집어넣어라.
d. 이런 단순한 대수 처리 방식에서는, 식에 붙은 연산자가 그 식의 타입을 나타낸다. 이때 '연산자와 타입’이 아니라 '타입과 연산자’로 프로시저 인덱스가 붙어 있다면, deriv 속에 알맞은 프로시저를 꺼내 쓰는 코드 dispatchingcode 가 다음과 같이 바뀐다.
((get (operator exp) 'deriv) (operands exp) var)
이 경우, 미분 시스템에는 어떤 변화가 필요한가?
문제로 부터 얻은 것
데이터 중심 프로그래밍 기법으로 프로시저를 짜면 확실히 몇가지 이점을 얻을 수 있다는 것을 알게 되었습니다.
패키지 내부의 프로시저를 숨길 수 있었습니다.
새로운 연산을 추가하기가 기존보다 훨씬 편했습니다. (additivity)
문제풀이
dr.racket에는 put과 get이 빌트인되어있지 않습니다. 아래의 코드를 사용하면 put과 get을 사용할 수 있습니다.
(define global-array '())
(define (make-entry k v) (list k v)) (define (key entry) (car entry)) (define (value entry) (cadr entry))
(define (put op type item) (define (put-helper k array) (cond ((null? array) (list(make-entry k item))) ((equal? (key (car array)) k) array) (else (cons (car array) (put-helper k (cdr array)))))) (set! global-array (put-helper (list op type) global-array)))
(define (get op type) (define (get-helper k array) (cond ((null? array) #f) ((equal? (key (car array)) k) (value (car array))) (else (get-helper k (cdr array))))) (get-helper (list op type) global-array))
그리고 교재의 2.3.2절의 프로시저 중, 이번 문제에 필요한 프로시저는 다음과 같습니다.
(define (make-sum x y) (cond ((=number? x 0) y) ((=number? y 0) x) ((and (number? x) (number? y)) (+ x y)) (else (list'+ x y))))
(define (make-product x y) (cond ((or (=number? x 0) (=number? y 0)) 0) ((=number? x 1) y) ((=number? y 1) x) ((and (number? x) (number? y)) (* x y)) (else (list'* x y))))
a. 프로시저의 원리
책의 2.4.3절에서는 데이터 중심 프로그래밍에 대해 설명하고 있습니다. 제가 이해한 데이터 중심 프로그래밍 기법은 데이터의 종류에 따라 가장 알맞은 연산을 적용하기 위한 프로그래밍 기법입니다. 위의 deriv는 연습문제 2.56에서 처음 만들었던 것 처럼, 수식에서 변수와 연산자를 뽑아내어 각각에 맞게 미분을 하는 프로시저입니다. 미분하는 대상이 변수인지 상수인지에따라 또, 연산자가 곱셈인지 덧셈인지에 따라 즉, 데이터의 타입에 따라 다른 방식으로 미분을 진행하므로, 데이터 중심 설계를 하기에 알맞다고 할 수 있습니다.
number?나 variable?같은 술어 프로시저를 모조리 데이터 중심 방식으로 다루지 못하는 이유는, 술어 프로시저가 적용될 가능성이 있는 모든 데이터를 연산표에 기록하는 것은 현실적으로 불가능하기 때문이라고 생각합니다.
b. 덧셈과 곱셈식을 미분하는 프로시저
원본 프로시저에 있던 +와 *을 데이터 중심 프로그래밍 방식으로 나타내면 됩니다. 미분 프로시저를 제대로 기억하고 있지 않거나, 교재의 put과 get의 용도를 이해하지 못했다면, 어렵게 느껴질 수도 있습니다. 여유를 가지고 페이지를 앞으로 넘겨서 제대로 복습하고 오시길 바랍니다.