이제까지 본 함수들은 항상 이름이 있다. 그런데 이름이 없는 함수도 있다. 이를 람다 함수라고 한다. 람다 함수를 정의하는 방법은 아래와 같다. define과 비교할 때 함수 이름이 없다는 점을 제외하면 나머지는 똑같다.
(lambda (인자 목록) (함수 내용) )
람다 함수의 용도에는 몇 가지가 있다. 하나는 이름을 굳이 붙여줄 필요가 없는 일회용 함수를 정의할 때다. 다음의 경우를 보자.
> (define (inc x) (+ x 1)) > (map inc '(1 2 3)) (2 3 4)
map은 함수를 리스트의 각 원소에 적용해주는 함수다. 그러니까 (map inc '(1 2 3))은 (list (inc 1) (inc 2) (inc 3))와 같다. 프로그램에서 inc를 여기서 딱 한 번 쓰고 말 것이라면 굳이 이름을 붙여줄 필요가 없다. 따라서 다음과 같이 바꿀 수 있다.
> (map (lambda (x) (+ x 1)) '(1 2 3)) (2 3 4)
람다 함수의 또다른 용도는 함수에서 함수를 생성할 때이다. 아래에서 born 함수는 출생연도 별로 현재 나이를 계산해주는 함수를 만든다. 철수-나이 함수는 1980년에 태어난 철수의 나이를 계산해주는 함수다. 2006년 현재 철수는 26살이다.
> (define (born 태어난-해) (lambda (올해) (- 올해 태어난-해))) > (define 철수-나이 (born 1980)) > (철수-나이 2006) 26
사실 함수 정의는 변수에 lambda 함수를 할당한 것을 간략히 표현한 것이다. 예를 들어 아래 두 표현은 동일하다.
> (define (add x y) (+ x y)) > (define add (lambda (x y) (+ x y)))
아래 코드의 계산 결과는 얼마일까?
> (define x 10) > (let ((x 5)) (+ x 1))
x는 10이고 (+ x 1)이니까 11일까? 아니다. 6이다. 왜냐하면 앞에 있는 let ((x 5)) 때문이다. 이 표현은 "이 괄호 안에서는 x를 5라고 하자"라는 뜻이다. 이때 이 x를 지역 변수라고 하고, 바깥쪽에 있는 x는 전역변수라고 한다. x 5 사이에 괄호가 두 개 겹쳐있는 이유는 원래 여러 개의 변수들을 정의할 수 있도록 되어있기 때문이다.
> (let ( (x 1) (y 2) ) (+ x y) ) 3
사실 let은 lambda 함수를 간단히 표기한 것에 지나지 않는다. 위의 표현을 다시 쓰면 아래와 같다.
> ((lambda (x y) (+ x y)) 1 2) 3
그렇다면 아래와 같은 경우는 어떻게 될까? x는 5라고 했고, y는 x라고 했으니 x와 y를 더하면 10이될까?
> (define x 1) > (let ( (x 5) (y x) ) (+ x y))
아니다. 6이 된다. 왜인지는 lambda 함수꼴로 다시 써보면 알 수 있다. (y x)에서 x는 지역변수 x가 아닌 전역변수 x다.
> (lambda (x y) (+ x y)) 5 x
그럼 지역변수를 이용해서 지역변수를 정해주고 싶다면 어떻게 할까? let을 겹쳐쓰면된다.
> (let ((x 5)) (let ((y x)) (+ x y))) 10
간단히 표현하려면 let* 함수를 사용하면 된다.
> (let* ( (x 5) (y x) ) (+ x y)) 10
마지막으로 이런 경우를 생각해보자. greeting 함수는 전역변수 world를 사용한다. 만약 world의 값을 잠시 바꿔주고 싶다면 어떻게 할까?
> (define world "world") > (define (greeting) (display (string-append "hello, " world))) > (greeting) hello, world
fluid-let을 이용하면 된다.
> (fluid-let ((world "universe")) (greeting)) hello, universe
fluid-let을 사용하려면 언어를 Standard (R5RS)에서 PLT 밑에 있는 언어들(Textual, Graphical, Pretty Big, Expander) 중에 하나로 바꿔주어야 한다. R5RS는 현재 스킴 표준으로 최소한의 함수와 문법만 포함하고 있다. PLT 밑에 있는 언어는 R5RS 스킴에 새로운 함수와 문법을 추가한 것이다. 리스프 계열의 언어들은 매크로라는 것을 이용해서 언어에 새로운 문법을 추가할 수 있다. 그 방법은 다른 글을 통해 설명하겠다.