2008년 07월 13일
SICP Exercise 연습문제 3.37
이 문제는 인자로 입력값과 출력값을 받는 것이 아니라
인자로 입력값을 받고 출력값을 내놓는 프로시저를 만드는 방식을 씁니다.
여기서는 식 중심 문법(expression-oriented format)이라 소개합니다.
이것에 대해 살펴보았지만 정확한 정의를 잘 모르겠습니다.OTL...

일단 문제에서 요구한 c-, c*, c/, cv 프로시저를 구현하였습니다.
그리고 책에 나와있는 예제를 그대로 따라해보았습니다.
문제없이 잘 되는군요.^^
이번 절은 아주 흥미있었습니다.
고등학생 때 물리와 화학 시간에 배운 수식이 있습니다.
![]()
http://en.wikipedia.org/wiki/Ideal_gas_law
이상 기체의 상태방정식으로 기억하고 있습니다.
해당 수식의 재미있는 점은 P, V, T가 실험으로 측정이 가능하다는 점입니다.
(n도 측정이 가능했는지 잘 기억이 나지 않습니다.
배운지 5년이 넘어가서...OTL...)
따라서 다른 모든 변수의 측정한다면 나머지 하나의 값을 저 수식을 통해 알 수 있습니다.
이는 기존의 배웠던 수식(예를 들어 F = ma)과는 느낌이 조금 달랐습니다.
예를 들었던 F = ma의 경우 질량은 무게를 측정하여,
가속도는 단위 시간당 움직이는 변화량을 통해 측정이 가능합니다.
하지만 힘을 측정하는 방법에 대해 기억이 없습니다.
(즉, 없다는 뜻이 아니라 배웠던 기억이 없다는 뜻입니다. 실제로 있을 수 있습니다.)
따라서 측정된 값인 m과 a를 통해 F를 유도하는 식으로 많이 쓰이는 것으로 기억합니다.
그렇기에 이상 기체의 상태방정식은 기존의 수식과 다른 느낌에 신기하게 생각했습니다.
하지만 지금까지 제가 배운 방식으로
해당 방정식을 실행하여 값을 구하는 프로시저를 구현한다면
인자로 변수 5개를 받아 4개는 P, V, n, T의 포인터를 할당하고,
하나는 비어있는 변수를 지정하도록합니다.
번호를 왼쪽에서부터 붙여 P : 1, V : 2, n : 3, T : 4로 합니다.
그리하여 이렇게 만들 것입니다.

잘되는 듯싶습니다.^^
하지만 그리 좋은 코드는 아니네요.
여하튼 이런 식으로 만들겠지만, constraint propagation을 쓰면 훨씬 깔끔합니다.
'이는 놀란 만치 시대를 앞서가는 생각이었다.'라는 주석에서도 그 대단함이 느껴집니다.
그리고 이런 생각은 이렇게 출발할 수 있다는 것을 알았습니다.
'디지털 회로를 보면 왼쪽에서 오른쪽, 위에서 아래로 나아간다.
그럼 반대로 동작하는 회로를 만들 때
즉, 입력과 출력이 고정이 아닌 양방향 입출력이라면
서로가 서로에게 영향을 미치니 이를 만든다면??'라는 질문에서 출발할 듯싶습니다.
하지만 그런 질문을 하지 못했다는 점에서 좌절을 느낍니다.OTL....
(역시 천재들은 다르구나.. 먼산....)
참조
해럴드 애빌슨, 김재우 역, <컴퓨터 프로그램의 구조와 해석>, 인사이트, 2007, pp. 384
(define true (= 0 0))
(define false (= 0 1))
;;;SECTION 3.3.5
(define (adder a1 a2 sum)
(define (process-new-value)
(cond ((and (has-value? a1) (has-value? a2))
(set-value! sum
(+ (get-value a1) (get-value a2))
me))
((and (has-value? a1) (has-value? sum))
(set-value! a2
(- (get-value sum) (get-value a1))
me))
((and (has-value? a2) (has-value? sum))
(set-value! a1
(- (get-value sum) (get-value a2))
me))))
(define (process-forget-value)
(forget-value! sum me)
(forget-value! a1 me)
(forget-value! a2 me)
(process-new-value))
(define (me request)
(cond ((eq? request 'I-have-a-value)
(process-new-value))
((eq? request 'I-lost-my-value)
(process-forget-value))
(else
(error "Unknown request -- ADDER" request))))
(connect a1 me)
(connect a2 me)
(connect sum me)
me)
(define (inform-about-value constraint)
(constraint 'I-have-a-value))
(define (inform-about-no-value constraint)
(constraint 'I-lost-my-value))
(define (multiplier m1 m2 product)
(define (process-new-value)
(cond ((or (and (has-value? m1) (= (get-value m1) 0))
(and (has-value? m2) (= (get-value m2) 0)))
(set-value! product 0 me))
((and (has-value? m1) (has-value? m2))
(set-value! product
(* (get-value m1) (get-value m2))
me))
((and (has-value? product) (has-value? m1))
(set-value! m2
(/ (get-value product) (get-value m1))
me))
((and (has-value? product) (has-value? m2))
(set-value! m1
(/ (get-value product) (get-value m2))
me))))
(define (process-forget-value)
(forget-value! product me)
(forget-value! m1 me)
(forget-value! m2 me)
(process-new-value))
(define (me request)
(cond ((eq? request 'I-have-a-value)
(process-new-value))
((eq? request 'I-lost-my-value)
(process-forget-value))
(else
(error "Unknown request -- MULTIPLIER" request))))
(connect m1 me)
(connect m2 me)
(connect product me)
me)
(define (constant value connector)
(define (me request)
(error "Unknown request -- CONSTANT" request))
(connect connector me)
(set-value! connector value me)
me)
(define (probe name connector)
(define (print-probe value)
(newline)
(display "Probe: ")
(display name)
(display " = ")
(display value))
(define (process-new-value)
(print-probe (get-value connector)))
(define (process-forget-value)
(print-probe "?"))
(define (me request)
(cond ((eq? request 'I-have-a-value)
(process-new-value))
((eq? request 'I-lost-my-value)
(process-forget-value))
(else
(error "Unknown request -- PROBE" request))))
(connect connector me)
me)
(define (make-connector)
(let ((value false) (informant false) (constraints '()))
(define (set-my-value newval setter)
(cond ((not (has-value? me))
(set! value newval)
(set! informant setter)
(for-each-except setter
inform-about-value
constraints))
((not (= value newval))
(error "Contradiction" (list value newval)))
(else 'ignored)))
(define (forget-my-value retractor)
(if (eq? retractor informant)
(begin (set! informant false)
(for-each-except retractor
inform-about-no-value
constraints))
'ignored))
(define (connect new-constraint)
(if (not (memq new-constraint constraints))
(set! constraints
(cons new-constraint constraints)))
(if (has-value? me)
(inform-about-value new-constraint))
'done)
(define (me request)
(cond ((eq? request 'has-value?)
(if informant true false))
((eq? request 'value) value)
((eq? request 'set-value!) set-my-value)
((eq? request 'forget) forget-my-value)
((eq? request 'connect) connect)
(else (error "Unknown operation -- CONNECTOR"
request))))
me))
(define (for-each-except exception procedure list)
(define (loop items)
(cond ((null? items) 'done)
((eq? (car items) exception) (loop (cdr items)))
(else (procedure (car items))
(loop (cdr items)))))
(loop list))
(define (has-value? connector)
(connector 'has-value?))
(define (get-value connector)
(connector 'value))
(define (set-value! connector new-value informant)
((connector 'set-value!) new-value informant))
(define (forget-value! connector retractor)
((connector 'forget) retractor))
(define (connect connector new-constraint)
((connector 'connect) new-constraint))
; exercise 3.37
(define (c+ x y)
(let ((z (make-connector)))
(adder x y z)
z))
; answer
(define (c- x y) ; x - y
(let ((z (make-connector)))
(adder z y x)
z))
(define (c* x y) ; x * y
(let ((z (make-connector)))
(multiplier x y z)
z))
(define (c/ x y) ; x / y
(let ((z (make-connector)))
(multiplier z y x)
z))
(define (cv value)
(let ((z (make-connector)))
(set-value! z value 'user)
z))
; exercise 3.37
(define (celsius-fahrenheit-converter x)
(c+ (c* (c/ (cv 9) (cv 5))
x)
(cv 32)))
(define C (make-connector))
(define F (celsius-fahrenheit-converter C))
; execute
(probe "Celsius temp" C)
(probe "Fahrenheit temp" F)
(set-value! C 25 'user)
(forget-value! C 'user)
(set-value! F 212 'user)
# by | 2008/07/13 09:04 | in OCW | 트랙백 | 덧글(0)















☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]