Languages/Erlang2008.09.08 20:05

Erlang은 함수형 언어이고, 모든 프로그래밍 행위가 함수를 정의하는 것에서부터 출발합니다. Erlang 함수에는 두 가지 종류가 있습니다.

1. 이름 있는 함수
2. 이름 없는 함수

이름 있는 함수의 예제는 지금까지 보셨으니 잘 아실테구요. (이름 있는 함수들은 C나 Java에서도 흔한 것이니까 이해하기도 쉬운 편이죠.) 이번 글에서는 이름 없는 함수를 살펴보겠습니다.

이름 없는 함수의 사례는 JavaScript 같은 프로그래밍 언어에서 쉽게 찾아볼 수 있습니다. 제가 예전에 JavaScript 관련 글을 적으면서 JavaScript에서는 함수도 객체다라는 이야기를 한 적이 있었는데요. 다음 예제를 한 번 보시죠.

function addGenerator( num ) {
    return function( toAdd ) {
       return num + toAdd;
   }
}

var addFive = addGenerator( 5 );

alert( addFive(4) == 9 );

위의 예제를 보면 함수가 함수를 반환하고 있고, 반환된 함수를 다시 호출하고 있습니다. Erlang에서도 당연히 이런 프로그래밍이 가능합니다. 가령 위와 똑같은 코드를 Erlang으로 작성해 본다면...

4> AddGenerator = fun(Num) -> ( fun(X) -> Num + X end ) end.
5> AddFive = AddGenerator(5).
6> AddFive(4).
9.

뭐 이렇게 되는 겁니다. 여기서 중요하게 보셔야 할 부분이 바로 fun()의 쓰임새인데요. JavaScript에서 function()이 익명의 함수 객체를 만들어 반환하는 데 쓰이는 것 처럼, fun()도 Erlang에서 같은 쓰임새를 가지고 있습니다.

Erlang에서 fun 정의는 fun 키워드로 시작해서 end로 끝납니다. 그러니까 이런 식이죠.

1> Mult = fun(X, Y) -> X * Y end.
2> Mult(3, 4)
12

정의한 fun을 변수에 대응시켜 변수 이름을 통해 호출하고 있습니다. fun도 함수인지라 일반 Erlang 함수와 같이 절을 가질 수 있습니다. 근데 fun에는 함수 이름이 없기 떄문에, 그 문법은 일반 함수와 조금 틀립니다. 가령, 다음의 fun을 한번 보시죠.

1> Max = fun(X, Y) when X>Y -> X; (X, Y) -> Y end.
#Fun<erl_eval.12.102015280>
2> Max(2,3).
3

이전 글에서 배웠던 Max 함수의 정의외 바교해 보면, 차이가 분명합니다. 적어줄 함수 이름이 없기 때문에, 괄호와 인자 리스트만 절 앞부분에 적어주는 것이죠.

이렇게 해서 만들어진 fun은 함수의 인자로 넘길 수 있습니다. 물론 이름 있는 함수들도 다른 함수의 인자로 전달할 수 있습니다. 하지만 fun을 사용하면 좀 더 재미있게(fun!) 코드를 작성할 수 있습니다. 예를 한번 살펴보죠. Erlang의 표준 라이브러리 lists라는 모듈에는 map이라는 함수가 정의되어 있습니다. 이 함수는 인자를 두 개 받는데요. 첫 번째 인자는 함수이고, 두 번째 인자는 리스트입니다. map은 두 번째 인자에 보관된 각각의 원소에 첫 번째 인자로 주어진 함수를 적용한 결과를 리스트 형태로 반환합니다. 다음의 코드를 보시죠.

5> Double = fun(X) -> 2 * X end.
#Fun<erl_eval.6.49591080>
6> L = [1, 2, 3, 4, 5].
[1,2,3,4,5]
7> lists:map(Double, L).
[2,4,6,8,10]

예상했던 결과죠? 그런데 저렇게 코드를 작성하는 대신 다음과 같이 해도 됩니다.

8> lists:map(fun(X) -> 2*X end, L).
[2,4,6,8,10]
9>

jQuery 써서 자바스크립트 프로그래밍 많이들 하시는 분은 아마 다음과 같은 형식에 꽤나 익숙하실텐데, 비슷한 형태의 문법이라고 할 수 있죠.

$(function() {
   ...
});

자. 지금까지 Erlang 함수가 fun이나 함수를 인자로 받을 수 있음을 살펴봤습니다. 뿐만 아니라, Erlang 함수는 fun을 반환(return)할 수도 있습니다. 이에 대한 예제는 맨 위의 AddGenerator 예제를 통해 살펴봤었죠. 그런데 Erlang 함수에서 다른 이름 붙은 Erlang 함수를 반환할 수는 있을까요?

됩니다. (첨엔 안된다고 썼었는데 죄송.)

다음과 같이 하면 됩니다.

-module(test)
-export([get_sum/0]).

sum(L) -> sum(L, 0).

sum([H|T], S) -> sum(T, H + S);
sum([], S) -> S.

get_sum() -> fun sum/1.

위와 같이 코드를 작성하셨으면 컴파일 해서 실행을 한 번 해 보죠.

1> c(test).
{ok,test}
2> X = test:get_sum().
#Fun<test.0.55022140>
3> X([1,2,3,4,5,6]).
21
4>

어쨌던 fun이라는 키워드를 사용하는 것이 요령입니다. /1과 같이 arity를 명시해 주는 부분도 잊으면 안되겠죠.

신고
Posted by 이병준
TAG , ,

소중한 의견, 감사합니다. ^^