2007년 08월 19일
[erlang] "hello, world" 소스 뜯어보기 + 팩토리얼.
이전에 설명한 "hello, world" 소스를 통해서 erlang의 기본적인 문법을 살펴보겠삼.
이전 포스트에서 작성해봤던 "Hello, World"을 통해서 erlang에 대해서 감을 더 잡아보겠삼.
<code>
-module(hello).
-export([hello/0]).
-import(io, [format/2]).
hello() -> io:format("Hello, World~n", []).
% EOF
</code>
가장 공통적인 부분은 주석은 '%'으로 시작해서 그 행의 마지막까지 이어진다는 것을 알 수 있습니다. (%EOF) 그리고 모든 행의 마지막은 "."으로 마치는 것을 알 수 있습니다.
erlang에서 가장 작은 코드의 단위는 함수로 나뉘며 함수나 기타 논리적인 집합을 모듈로서 정리합니다. 다른 언어들처럼 클래스나 또 다른 코드의 집합을 나타내는 방법이 없으며 반드시 모듈/애플리케이션(erlang 시스템은 애플리케이션들간의 유기적인 조합으로 구성됩니다.)을 통해서 나타내며, 값, 함수, 구조체(record)등은 반드시 모듈에 속합니다.
우리의 예제도 하나의 정말 작은 애플리케이션이므로 이 애플리케이션을 나타내는 모듈을 선언해줬습니다.
"-module(hello)" : 모듈의 이름은 hello입니다. 문자열등을 사용할 필요없이 이후에 설명할 심볼을 통해서 모듈을 지정해줍니다.
다음줄에서 "-export(...)"의 역활은 이 모듈에 대해 외부에서 접근할 수 있도록 수출하는 함수의 목록을 지정합니다. 함수의 목록은 이후에 설명할 함수표식(function signature)을 포함하는 리스트를 적어줍니다. "[...]"와 같이 사각괄호는 리스트 자료형을 표현하는데 사용되며, "hello/0"와 같은 것을 함수표식이라고 하는데 이는 함수의 이름되는 심볼과 '/'로 구분하여 그 함수의 인자의 갯수를 적어줍니다. (erlang은 되돌림 값은 언제나 하나이고, 인자의 갯수도 고정인자만을 허용합니다. 대신 리스트나 튜플등을 이용하여 다수의 값을 되돌리거나 받을 수 있으므로 제한점은 아닌것 같습니다. 또한 이를 통해 같은 심볼로 나타내는 함수라도 그 함수표식이 다르면 아예 다른 함수로 취급함을 예측해볼수있습니다.)
간단히 리스트에 대해서 설명을 하고 넘어가겠습니다. 다른 함수형언어들과 마찬가지로 erlang도 리스트를 기본자료형으로서 제공합니다. 헤스켈과 같은 언어와 달리 리스트의 내용은 서로 자료형이 다를 수 있습니다.
<code>
> [1, 'a', "b"].
...
</code>
리스트의 표현과 관련하여 리스트의 원소들을 일일이 이렇게 나열하는 방법이외에도 리스트표현식이나 패턴매칭에서 리스트을 표현하는 방법과 같은 확장적인 주제에 대해서는 이후로 미뤄두고 우선은 이와 같이 리스트를 나타낸다는 것만을 알아두고 넘어가겠습니다.
그 다음줄의 "-import(...)"은 hello 모듈이 아닌 다른 모듈에서 "-export(...)"하여 제공한 함수를 이 모듈에서 사용하겠다는 것을 나타냅니다. "-import(...)"의 인자는 2개입니다. 첫번째 인자는 외부모듈의 심볼, 두번째는 해당 모듈로부터 사용할 함수들의 함수표식들을 "-export(...)"에서 지정했던과 같은 요령으로 지정해줍니다. 이 예제에서는 표준출력으로 출력만을 할것이므로 "io:format/2"을 지정하고 있습니다.
이렇게 "-Tag(Arg...)"와 같이 '-'으로 시작하는 문장들을 module attribute라고 합니다. 이들은 자유롭게 사용자가 지정할수도 있지만, c/c++의 preprocessor와 같이 컴파일러에게 해당 모듈을 어떻게 처리할지를 지정하는 역활도 합니다. 또한 이를 통해서 c/c++에서 하는것처럼 다른 소스파일을 포함(include)하거나 cpp스타일의 매크로를 선언하거나 이후에 설명할 구조체(record)을 선언하는 역활도 수행합니다.
"hello() -> io:format("Hello, World~n", [])."
: 이 행은 "hello/0"의 함수를 선언합니다. "->"의 좌변은 함수의 이름과 괄호안에는 인자들의 목록을 나열해줍니다. 그리고 그 우변에는 실제로 그 함수의 내용을 적어줍니다. erlang에서 함수이름등과 같은 규칙은 파이썬과 유사합니다. 파이썬도 그 '이름'과 함수값이 연관을 갖는것처럼 말입니다. 다음을 봐주세요.
<code>
>>> dir
<built-in function dir>
>>> dir()
['__builtins__', '__doc__', '__name__']
</code>
위의 파이썬 쉘 세션에서 "dir"을 평가했을때 단순히 그 이름과 연관된 함수객체를 되돌렸습니다. 하지만 그 이름의 뒤에 "(...)"을 더해서 평가하자 그때서야 그 함수를 실행하여 평가를 하였습니다. 이와 유사하게 erlang에서도 함수는 심볼과 연관이 있지만 실제로 함수를 실행하기 위해서는 "(...)"을 사용하여 그 인자들을 넘겨줍니다.
또한, 함수가 다른 모듈에 속해있는 경우에는 ":"을 포함하여 그 함수이름 앞에 모듈의 이름을 적어줍니다.
여기서는 "io"모듈의 "format/2" 함수를 실행하였습니다. "io:format/2"의 인자는 두개이고, 첫번째는 형식문자열(format string), 두번째는 형식문자열에 따른 그 형식을 구성하기 위한 값들을 담은 리스트입니다. 여기서는 형식문자열이 필요로하는 다른 값이 없으므로 리스트는 비어있습니다.
"io:format"은 커먼리습의 "format"와 유사합니다. 우선 "~n"와 같이 형식문자열에서 주어진 인자들로부터 대체하거나 특별한 escape을 표현합니다. 우선 여기서는 "~n"은 개행문자를 표현한다고만 하고 넘어가겠습니다. (문자열의 내부에서 백슬래쉬를 이용하여 escape-sequence을 표현하는 방법도 erlang은 지원합니다.)
이 소스는 "hello:hello/0"이라는 안녕세상! 메시지를 출력하는 함수를 선언하고 있습니다.
조금 더 실용적일 factorial 예제와 간단한 주석을 남기고 이번 포스트를 정리합니다.
<code>
-module(factorial).
-export([fac1/1, fac2/1]).
-author("ageldama").
%% factorial with guard.
fac1(N) when N < 2 ->
1;
fac1(N) ->
fac1(N - 1) * N.
%% plain factorial with if-statement.
fac2(N) ->
if
N < 2 ->
1;
true ->
fac2(N - 1) * N
end.
</code>
이전 포스트에서 작성해봤던 "Hello, World"을 통해서 erlang에 대해서 감을 더 잡아보겠삼.
<code>
-module(hello).
-export([hello/0]).
-import(io, [format/2]).
hello() -> io:format("Hello, World~n", []).
% EOF
</code>
가장 공통적인 부분은 주석은 '%'으로 시작해서 그 행의 마지막까지 이어진다는 것을 알 수 있습니다. (%EOF) 그리고 모든 행의 마지막은 "."으로 마치는 것을 알 수 있습니다.
erlang에서 가장 작은 코드의 단위는 함수로 나뉘며 함수나 기타 논리적인 집합을 모듈로서 정리합니다. 다른 언어들처럼 클래스나 또 다른 코드의 집합을 나타내는 방법이 없으며 반드시 모듈/애플리케이션(erlang 시스템은 애플리케이션들간의 유기적인 조합으로 구성됩니다.)을 통해서 나타내며, 값, 함수, 구조체(record)등은 반드시 모듈에 속합니다.
우리의 예제도 하나의 정말 작은 애플리케이션이므로 이 애플리케이션을 나타내는 모듈을 선언해줬습니다.
"-module(hello)" : 모듈의 이름은 hello입니다. 문자열등을 사용할 필요없이 이후에 설명할 심볼을 통해서 모듈을 지정해줍니다.
다음줄에서 "-export(...)"의 역활은 이 모듈에 대해 외부에서 접근할 수 있도록 수출하는 함수의 목록을 지정합니다. 함수의 목록은 이후에 설명할 함수표식(function signature)을 포함하는 리스트를 적어줍니다. "[...]"와 같이 사각괄호는 리스트 자료형을 표현하는데 사용되며, "hello/0"와 같은 것을 함수표식이라고 하는데 이는 함수의 이름되는 심볼과 '/'로 구분하여 그 함수의 인자의 갯수를 적어줍니다. (erlang은 되돌림 값은 언제나 하나이고, 인자의 갯수도 고정인자만을 허용합니다. 대신 리스트나 튜플등을 이용하여 다수의 값을 되돌리거나 받을 수 있으므로 제한점은 아닌것 같습니다. 또한 이를 통해 같은 심볼로 나타내는 함수라도 그 함수표식이 다르면 아예 다른 함수로 취급함을 예측해볼수있습니다.)
간단히 리스트에 대해서 설명을 하고 넘어가겠습니다. 다른 함수형언어들과 마찬가지로 erlang도 리스트를 기본자료형으로서 제공합니다. 헤스켈과 같은 언어와 달리 리스트의 내용은 서로 자료형이 다를 수 있습니다.
<code>
> [1, 'a', "b"].
...
</code>
리스트의 표현과 관련하여 리스트의 원소들을 일일이 이렇게 나열하는 방법이외에도 리스트표현식이나 패턴매칭에서 리스트을 표현하는 방법과 같은 확장적인 주제에 대해서는 이후로 미뤄두고 우선은 이와 같이 리스트를 나타낸다는 것만을 알아두고 넘어가겠습니다.
그 다음줄의 "-import(...)"은 hello 모듈이 아닌 다른 모듈에서 "-export(...)"하여 제공한 함수를 이 모듈에서 사용하겠다는 것을 나타냅니다. "-import(...)"의 인자는 2개입니다. 첫번째 인자는 외부모듈의 심볼, 두번째는 해당 모듈로부터 사용할 함수들의 함수표식들을 "-export(...)"에서 지정했던과 같은 요령으로 지정해줍니다. 이 예제에서는 표준출력으로 출력만을 할것이므로 "io:format/2"을 지정하고 있습니다.
이렇게 "-Tag(Arg...)"와 같이 '-'으로 시작하는 문장들을 module attribute라고 합니다. 이들은 자유롭게 사용자가 지정할수도 있지만, c/c++의 preprocessor와 같이 컴파일러에게 해당 모듈을 어떻게 처리할지를 지정하는 역활도 합니다. 또한 이를 통해서 c/c++에서 하는것처럼 다른 소스파일을 포함(include)하거나 cpp스타일의 매크로를 선언하거나 이후에 설명할 구조체(record)을 선언하는 역활도 수행합니다.
"hello() -> io:format("Hello, World~n", [])."
: 이 행은 "hello/0"의 함수를 선언합니다. "->"의 좌변은 함수의 이름과 괄호안에는 인자들의 목록을 나열해줍니다. 그리고 그 우변에는 실제로 그 함수의 내용을 적어줍니다. erlang에서 함수이름등과 같은 규칙은 파이썬과 유사합니다. 파이썬도 그 '이름'과 함수값이 연관을 갖는것처럼 말입니다. 다음을 봐주세요.
<code>
>>> dir
<built-in function dir>
>>> dir()
['__builtins__', '__doc__', '__name__']
</code>
위의 파이썬 쉘 세션에서 "dir"을 평가했을때 단순히 그 이름과 연관된 함수객체를 되돌렸습니다. 하지만 그 이름의 뒤에 "(...)"을 더해서 평가하자 그때서야 그 함수를 실행하여 평가를 하였습니다. 이와 유사하게 erlang에서도 함수는 심볼과 연관이 있지만 실제로 함수를 실행하기 위해서는 "(...)"을 사용하여 그 인자들을 넘겨줍니다.
또한, 함수가 다른 모듈에 속해있는 경우에는 ":"을 포함하여 그 함수이름 앞에 모듈의 이름을 적어줍니다.
여기서는 "io"모듈의 "format/2" 함수를 실행하였습니다. "io:format/2"의 인자는 두개이고, 첫번째는 형식문자열(format string), 두번째는 형식문자열에 따른 그 형식을 구성하기 위한 값들을 담은 리스트입니다. 여기서는 형식문자열이 필요로하는 다른 값이 없으므로 리스트는 비어있습니다.
"io:format"은 커먼리습의 "format"와 유사합니다. 우선 "~n"와 같이 형식문자열에서 주어진 인자들로부터 대체하거나 특별한 escape을 표현합니다. 우선 여기서는 "~n"은 개행문자를 표현한다고만 하고 넘어가겠습니다. (문자열의 내부에서 백슬래쉬를 이용하여 escape-sequence을 표현하는 방법도 erlang은 지원합니다.)
이 소스는 "hello:hello/0"이라는 안녕세상! 메시지를 출력하는 함수를 선언하고 있습니다.
조금 더 실용적일 factorial 예제와 간단한 주석을 남기고 이번 포스트를 정리합니다.
<code>
-module(factorial).
-export([fac1/1, fac2/1]).
-author("ageldama").
%% factorial with guard.
fac1(N) when N < 2 ->
1;
fac1(N) ->
fac1(N - 1) * N.
%% plain factorial with if-statement.
fac2(N) ->
if
N < 2 ->
1;
true ->
fac2(N - 1) * N
end.
</code>
이 글과 관련있는 글을 자동검색한 결과입니다 [?]
- [erlang] 개발환경 세팅 및 "hello, world" 몸풀기. by 아겔
- "Programming Erlang"을 읽기 시작하며. by 아겔
- C 언어 - 4. Hello world!! by Taeyoung
- Ruby Symbol, Erlang Atoms. by monaca
- 얼랭(Erlang) 시작하기 - 1.1 여는 말 by 만성피로
# by | 2007/08/19 14:46 | erlang -- nine 9's | 트랙백




☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]