갈루아의 반서재



전역 함수 정의하기

사용자가 입력한 값이 정답보다 큰지 작은지에 따라 반응을 내보내는 guess-my-number 라는 게임에는 guess-my-number, smaller, 그리고 bigger 라는 3개의 전역 함수가 필요하다. 그리고 초기값을 정의할 start-over 함수도 필요하다. Common Lisp 에서 함수는 defun 이라는 함수를 통해 정의한다. 먼저 함수의 이름과 인수를 정의해보자.

첫번째로 정의해야할 함수는 guess-my-number 이다. 이 함수는 사용자의 추측을 이끌어내기 위해 *big* 과 *small* 변수를 사용한다. 다음과 같다. 함수이름 뒤에 위치한 ( ) 는 요구되는 파라메터가 없다는 표시이다. 

1
2
3
4
5
[1]> (defun guess-my-name ()
         (ash (+ *small* *big*-1))
GUESS-MY-NAME
[2]> (ash 11 1)
22
cs

defun 명령에 대해서는 기본적으로 새로 생성된 함수의 이름을 반환한다. 

그러면 이 함수는 어떤 역할을 하는가? 앞서 살펴보았듯이 컴퓨터의 추측값은 상한, 하한 사이의 값이 될 것이다. 이 결과를 낳기 위해서 우리는 2가지 값의 평균을 선택해야 한다. 그리고 그 값이 정수로 끝나지 않는다면 정수에 가까운 수를 선택할 수 있도록 해야 한다. 

먼저 상한과 하한값을 정하는 기능을 구현했다. 그리고 ash (arithmetic shift) 기능을 이용하여 두 값의 합을 이등분한 후 그 결과값을 줄였다. [2]의 (+ *small* *big*) 라는 부분이 2개의 변수를 더 하는 역할을 한다. 그리고 그 결과값은 ash 함수로 전달된다. 

리스프에 내장되어 있는 ash 라는 함수는 숫자를 이진 형태로 취급한다. 그리고 이진 비트를 좌우로 이동시킨다. 예를 들면, 정수 11은 이진수로 1011 로 표시되는데, [4]와 같이 (ash 11 1) 와 같이 대입하면 왼쪽으로 한 자리씩 이동하게 되어 10110 이 된다. 즉 십진수로 22가 되는 것이다. 반면  (ash 11 -1) 을 통해 우측으로 한 자리 이동시키면 101 이 되어 십진수 5가 된다. ash 함수를 사용함으로써 우리는 가능한 숫자의 범위를 최종 정답과 가깝게 줄여나갈 수 있다. 아래에서 보듯이 프로그램은 최초 상한과 하한값인 1과 100의 중간이 50을 선택했음을 볼 수 있다.


1
2
3
4
5
6
7
8
9
[1]> (defparameter *small* 1)
*SMALL*
[2]> (defparameter *big* 100)
*BIG*
[3]> (defun guess-my-number ()
         (ash (+ *small* *big*-1))
GUESS-MY-NUMBER
[4]> (guess-my-number)
50
cs