Practice/Lisp

Lisp에서 lexical과 dynamic 변수 타입

Lisp에는 lexical과 dynamic이라는 두가지 변수(variables) 형태가 존재한다.


lexical 변수는 C나 Java 같은 언어에서 말하는 지역(local) 변수를 생각하면 된다.
함수의 매개변수(parameters)나 LET 구문의 변수가 이런 타입니다.


함수의 매개변수

(defun foo (x y) (+ x y))

함수를 호출하면, 이 함수에 전달하는 인자(arguments)와 연결(binding)하는 매개변수를 생성한다.
이 변수는 함수 내로 범위가 한정된다.


LET 구문의 변수

(let ((x 10) (y 20)) (+ x y))

LET 구문 역시 함수 호출과 동일한 효과를 가진다.
LAMBDA로 표현하면 함수의 매개변수와 동일한 형태라는 것을 알 수 있다.

((lambda (x y) (+ x y)) 10 20)


dynamic 변수는 전역(global) 변수와 유사한다.


dynamic 변수는 DEFVAR, DEFPARAMETER 구문으로 생성한다.

(defvar *x* 10)
(defparameter *y* 20)


dynamic 변수를 special 변수라고도 불린다.
dynamic 변수는 자동적으로 전역적인 special 변수가 되기 때문이다.
special 변수와 같은 이름의 변수를 lexical 환경에서 생성하면 lexical이 아닌 dynamic 연결을 가진다.


(defparameter *y* 10)
(defun plus-*y* (x) (+ *y* x))

의 환경에서 *Y*는 special 변수이다.


special 변수가 환경에 따라서 어떻게 다르게 동작하는지 PLUS-*Y*로 실험해보자.

CL-USER> (plus-*y* 5)
15

예상한대로 '10 + 5'의 결과인 '15'를 반환했다.

다른 환경에서, PLUS-*Y*로 실험해보자.

CL-USER> (let ((*y* 20)) (plus-*y* 5))
25

예상과 다르게 '25'를 돌려주었다.


PLUS-*Y*의 몸체

(+ *y* x)
에서 정의된 *Y*는
(defparameter *y* 10)

를 참고할 것 같다.
그런데, 앞서 설명한대로, *Y*는 special 변수이고 PLUS-*Y*를 호출한 환경

(let ((*y* 20)) (plus-*y* 5))

에 동일 이름의 *Y*가 존재한다.
결국, LET 구문의 *Y*의 변수가 dynamic 연결을 가짐으로 값 '20'이 PLUS-*Y* 에서 사용되었다.[각주:1]


2013/01/17 - [Practice/Lisp] - DEFPARAMETER와 DEFVAR의 차이

2016/02/18 - [Practice/Lisp] - Lisp에서 클로저(closures)


  1. dynamic과 closure를 혼동하는 경우가 많다. closure에 대해서는 <a href="http://unipro.tistory.com/191" target="_blank">Lisp에서 클로저(closures)</a>를 참고하라. [본문으로]
저작자 표시 변경 금지
신고

알림

이 블로그는 구글에서 제공한 크롬에 최적화 되어있고, 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

카운터

Today : 20
Yesterday : 111
Total : 171,005