(let ((counter 0))
(defun reset ()
(setf counter 0))
(defun stamp ()
(setf counter (+ counter 1))))
> (list (stamp) (stamp) (reset) (stamp))
(1 2 0 1)
지역변수 counter의 값이 0으로 설정된 상태에서 counter를 0으로 셋팅하는 함수 reset과 counter 값을 1 늘리는 stamp 함수를 선언하였다. stamp함수를 호출할 때마다 counter 값이 늘어나는 것을 볼 수 있다. 지역변수가 소멸하지 않고 바인딩이 계속 살아 있는 것이다. 하지만 counter는 지역 변수이기 때문에 외부에서 접근하거나 볼 수가 없다. 오로지 reset과 stamp를 통해서만 접근할 수 있는 것이다.
마치 가방 안에 어떤 물건을 넣고 가방을 닫으면(close over => closure) 가방을 열 때도 그 물건이 있는 것과 같이 함수나 코드 블록이 생성될 때 특정 지역변수에 대한 바인딩이 있으면 함수와 바인딩이 같이 살아있게 되는 것을 가리켜 클로저라고 하는 것 같다.
다른 예를 보자.
(defun make-adder (n)
#’(lambda (x)
(+ x n)))
> (setf add3 (make-adder 3))
#
> (funcall add3 2)
5
> (setf add27 (make-adder 27))
#
> (funcall add27 2)
29
make -adder는 n을 인자로 받아서 '어떤 인자를 받으면 n을 더해서 리턴하는 함수'를 리턴하는 함수다. (setf add3 (make-adder 3))은 3을 더해서 리턴하는 함수를 만들어서 add3이라는 변수에 저장한 것이다. add3과 add27을 보면 각각의 함수가 그 함수가 만들어질 때 파라미터로 주어진 n 값의 바인딩을 그대로 가지고 있는 것을 볼 수 있다.
댓글 없음:
댓글 쓰기