SICP 연습문제 1.5 친절한 풀이

문제

언어 실행기가 인자먼저 계산법을 따르는지 정의대로 계산법을 따르는지 알아보고 싶어서 아래와 같은 프로시저를 정의했다.

(define (p) (p))

(define (test x y)
(if (= x 0)
0
y))

(test 0 (p))

인자먼저 계산법을 따르는 실행기라면 어떤 결과를 보게 될까? 정의대로 계산법을 따르는 실행기라면 어떤 결과를 보게 될까? 저마다 왜 그런 답이 나오는지 밝혀라

문제로 부터 얻은 것

인자먼저 계산법으로 계산했을 때 프로시저가 정상적으로 완료될 수 없는 상황도 있습니다. 인자의 계산이 끝나지 않을 수 있기 때문입니다.

문제풀이

이 문제를 풀기 위해서는 각 방법의 정의를 정확하게 알아야 합니다.

a. 인자먼저 계산법

(test 0 (p))

위 프로시저를 실행할 때 인자먼저 계산법대로 실행한다고 해봅시다. 인자먼저 계산법은 test 프로시저의 인자인 0과 p가 더이상 계산될 수 없을 때까지 계산한 후 반환값을 인자로 삼아서 프로시저를 실행할 것입니다. 그런데 p는 자기 자신을 계속 반환하는 함수이므로, 정상적으로 계산을 끝마칠 수 없습니다. 그러므로 test 프로시저는 p의 반환값을 영원히 받을 수 없기 때문에 완료되지 않습니다.

b. 정의대로 계산법

(test 0 (p))

반대로 정의대로 계산법은 위 프로시저를 우선 정의된대로 바꿉니다.

(if (= 0 0)
0
(p))

그리고 문제에서 if식을 실행할 때에는 술어의 참 거짓 유무에 따라 한가지 계산식만 계산한다고 하였으므로,
(= 0 0)이 참인 시점에서 p는 실행되지 않고 test프로시저는 0을 반환합니다.

유저 브레이크로 종료된 모습

하지만 실험해 보니 현재 버전의 Dr.Racket은 인자먼저 계산법을 사용하는 것 같습니다. 프로시저가 정상종료되지 못해 유저가 직접 종료한 모습입니다.

c. 번외

그런데 기존의 코드를 아래와 같이 바꾸면 기존과는 다른 결과를 볼 수 있습니다.

;기존의 코드
(test 0 (p))

;새로운 코드
(test 0 p)

0을 반환한 체로 무사히 종료된 프로세스

정확한 것은 아니지만, 괄호로 묶여있는 (p)는 프로시저를 호출하여 실행한 결과라는 의미이고, p는 프로시저가 있는 위치만을 의미하는 것 같습니다.

읽어주셔서 감사합니다.