2장에서는 전역변수 및 전역함수, 지역변수 및 지역함수, 기본적인 CLISP의 사용 등이 나옵니다.
리스프에서 전역변수
리스프에서 전역으로 선언된 변수를 최상위 정의(top-level definition)라 부릅니다. defparameter 함수를 이용해서 최상위 정의를 할 수 있습니다.
정의 - defparameter
기본형)
> (defparameter *name* value) |
defparameter의 첫번째 매개변수 : 새로운 변수 이름
defparameter의 두번째 매개변수 : 값
새로운 변수의 이름은 * 기호로 감싸주어야합니다.(* 기호는 귀마개 라는 애칭... 을 쓴다고 하네요... 하...)
리스프는 * 기호를 변수 이름의 일부분으로 인식하고 이를 무시합니다. 리스퍼(리스프 프로그래머)는 관습처럼 전역변수에 * 기호를 붙여 지역변수와 구분하기 쉽게 해줍니다.
foo 라는 전역변수를 정의하며 17로 값을 지정해보았습니다. REPL에 *FOO*가 출력됩니다.
defparameter는 최상의 정의 명령이 제대로 실행 된 경우, 정의 된 변수 이름을 REPL에 출력합니다.
최상위 정의의 예)
> (defparameter *foo* 17) *FOO* |
REPL에 *foo*를 입력하면, 정의된 변수의 값이 출력됩니다.
전역변수 사용예)
> *foo* 17 |
이미 정의 된 변수 이름을 다시 defparameter로 정의하게 되면, 이전 값은 새로운 갚으로 덮어씌워집니다.
사용 예)
> (defparameter *foo* 24) *FOO* > *foo* 24 |
값 변경 - setf
defparameter를 다시 호출해서 값을 새로운 갚으로 덮어씌우는 것 말고, 이미 정의 된 변수의 값을 변경하는 함수가 있습니다.
기본형)
> (setf *name* value) |
setf의 첫번째 매개변수: 이미 정의된 전역변수의 이름
setf의 두번째 매개변수: 변경할 값(새로운 값)
setf 사용예)
> (defparameter *bar* 17) *BAR* > *bar* 17 > (setf *bar* 24) 24 |
리스프에서의 전역함수
커먼 리스프(CLISP)에서 함수는 defun 명령으로 정의할 수 있습니다.
정의 - defun
기본형)
> (defun function-name (arguments) ......) |
첫 부분에는 함수의 이름과 매개변수를 정의하고, 그 다음으로 함수의 로직을 구성하는 코드를 작성합니다.
함수 선언 및 사용 예)
> (defparameter *foo* 10) *FOO* > (defparameter *bar* 5) *BAR* > (defun get-foo-plus-bar () (+ *foo* *bar*) ) GET-FOO-PLUS-BAR > (get-foo-plus-bar) 15 |
LISP는 return 처럼 값을 반환하는 명령이 필요 없습니다. 함수 내부 코드에서 마지막으로 계산된 결과가 자동으로 반환되기 때문이죠.
위의 함수, get-foo-plus-bar를 보면, 매개변수는 없고, *foo*와 *bar*를 더해주는 코드만 있을 뿐입니다. LISP에서는 전위표기식 연산을 사용합니다. 이 함수에서는 마지막 계산된 결과가 *foo*(10) + *bar*(5), 즉 15이기때문에 15를 자동으로 반환하고, 이를 REPL이 출력해준것입니다.
리스프에서 지역변수
한 함수 내에서만 또는 코드의 일정 부분에서만 쓰도록 변수와 함수를 제한할 수 있습니다. 이를 지역변수와 지역함수라고 하는데, 여기서는 지역변수를 먼저 살펴봅니다.
정의 - let
지역변수의 정의는 let을 사용합니다.
기본형)
> (let (variable declarations) ...body... ) |
let의 첫번째 매개변수: 변수 정의 목록 - 한 개 이상의 지역 변수를 정의할 수 있습니다.
let의 body 부분: 이 부분에서만 변수 정의 목록에 정의해둔 변수를 사용할 수 있습니다.
let의 사용예)
> (let ( (foo 10) (bar 5) ) (+ foo bar) ) 15 |
예시에서는 foo에 10, bar에 5를 각각 정의 하였고, 이를 body 부분에서 사용해서 연산하였습니다.
let을 사용할때는, 변수 정의 목록 전체를 괄호() 로 둘러 싸야합니다. 또 변수의 이름과 변수의 값, 즉 한 쌍을 괄호로 둘러싸야합니다. 일반적으로 이름-값 정의를 할때, 정의된 변수 부분에 세로로 줄을 맞추는 것이 관례라고 합니다.
리스프에서 지역함수
지역변수를 정의할때는 let 함수를 사용했습니다. 함수는 function이라고 하죠. 리스프에서 지역함수를 정의할때는 flet 함수를 사용합니다.
정의 - flet
기본형)
> (flet ( (function_name (arguments) ...function body...) ) ... body ... ) |
flet의 첫번째 매개변수: 첫 번째 인자에서 함수를 정의합니다.
여기서는 ( (function_name (arguments) ... function body...) ) 부분입니다.
flet의 body: 첫번째 매개변수로 정의된 함수를 body 부분에서 사용합니다.
함수 정의 부분: 함수 정의 부분은 함수의 이름과 매개변수, 그리고 함수의 바디로 구성됩니다.
flet의 사용 예)
> (flet ((f (n) (+ n 10))) (f 5)) 15 |
let 처럼 flet에서도 여러 함수를 정의하고 사용할 수 있습니다. 방식은 let과 같고, 괄호가 많아지니 신경써야 하죠.
flet, 여러 함수 정의 및 사용 예)
> (flet ( (f (n) (+ n 10)) (g (n) (- n 3))) (g (f 5))) 12 |
f와 g라는 함수를 정의하였고, body 부분에서 f(5)를 먼저 계산한 후, 그 값을 다시 g에 넣어서 계산한 결과를 보여줍니다. 위의 예에서는 최종 결과로 12가 나옵니다.
정의 - labels
지역함수를 하나 만들고, 그 지역함수를 다른 지역함수안에서 사용하고 싶을때가 있습니다.
그럴때는 labels 함수를 사용해서 정의하고 사용할 수 있습니다. 기본 구조는 flet 함수와 동일 합니다.
labels 사용 예)
> (labels ( (f (n) (+ n 10)) (g (n) (- (a n) 3))) (g 5)) 12 |
labels는 다른 지역 함수를 실행 할 수 있게 하고, 자기 자신을 다시 실행(재귀 호출)할 수도 있습니다.
'General > LISP' 카테고리의 다른 글
[LISP #1] CLISP로 시작하기 - 설치와 실행 (1) | 2012.01.23 |
---|---|
[LISP #0] Land of LISP - 만들면서 배우는 리스프 프로그래밍 (0) | 2012.01.21 |