데이터 타입

데이터 타입 (Data Types)

에를랭은 이번 글에서 나열할 여러 데이터 타입을 제공해요. 이 글은 에를랭의 각 데이터 타입이 정확히 무엇이고, 어떻게 쓰이는지 하나씩 살펴보는 내용입니다.

출처: Erlang 공식 문서 - Data Types

먼저 짚고 넘어갈 점이 있어요. 에를랭에는 사용자 정의 타입이 없고, 오직 에를랭 용어(term)로 만들어진 합성 타입(데이터 구조)만 있습니다. 이 말은 합성 타입을 검사하는 함수(보통 is_type/1이라는 이름)가, 선택된 표현과 우연히 일치하는 용어에 대해 true를 반환할 수 있다는 뜻이에요. 내장 타입에 대응하는 함수는 이런 문제가 없습니다.

용어 (Terms)

어떤 데이터 타입의 데이터 조각을 _용어(term)_라고 해요.

숫자 (Number)

숫자 리터럴에는 _정수(integer)_와 부동소수점(float) 두 종류가 있어요. 관례적인 표기 외에 에를랭 특유의 표기 세 가지가 더 있습니다:

  • $char
    문자 _char_의 ASCII 값 또는 유니코드 코드포인트.
  • base#digits
    밑(base)이 _base_인 정수. _base_는 2부터 36 사이의 정수여야 해요. _digits_는 0-9와 문자 A-Z(대문자 또는 소문자)입니다. 이 표기는 Ada 프로그래밍 언어에서도 찾아볼 수 있어요. 에를랭은 16진수의 0x나 8진수의 077 같은 접두어를 지원하지 않습니다.
  • base#digits.digits#eexponent
    밑이 있는 부동소수점 숫자. 예: 16#ff.fe#e+6. 16나 2 같은 밑을 쓰면 부동소수점 숫자의 정확한 텍스트 표현이 가능해요. 밑과 마찬가지로 지수도 항상 십진수입니다.

앞에 붙은 0은 무시됩니다. 단일 밑줄 문자(_)를 숫자 사이에 시각적 구분자로 넣을 수 있어요.

또한 부동소수점 숫자는 반드시 숫자로 시작해야 하고, .을 포함해야 합니다. 다시 말해 .01이나 1e6 같은 리터럴은 허용되지 않으며, 각각 0.011.0e6으로 써야 해요.

예시:

1> 42.
42
2> -1_234_567_890.
-1234567890
3> $A.
65
4> $\n.
10
5> 2#101.
5
6> 16#1f.
31
7> 16#4865_316F_774F_6C64.
5216630098191412324
8> 2.3.
2.3
9> 2.3e3.
2.3e3
10> 2.3e-3.
0.0023
11> 1_234.333_333
1234.333333
12> 36#helloworld.
1767707668033969

비교 (Comparisons)

정수와 부동소수점은 모두 같은 선형 순서를 공유합니다. 즉 12.4보다 작게 비교되고, 32.99999보다 크게 비교되며, 55.0과 같습니다.

정수끼리 또는 부동소수점끼리 비교하고 싶을 때 용어 동치 연산자(=:=, =/=)나 패턴 매칭을 쓰고 싶어질 수 있어요. 정수는 숫자마다 구별되는 표현을 가지므로 이 방식이 잘 동작하지만, 부동소수점에는 놀라운 경계 사례가 있습니다. 부동소수점은 0에 대한 표현이 두 개 있어서 용어 동치 연산자와 패턴 매칭이 그것들을 서로 다르게 보거든요.

부동소수점 숫자를 수치적으로 비교하고 싶다면 일반 비교 연산자(예: ==)를 쓰고, 두 인자가 모두 부동소수점이길 요구하는 가드를 추가하세요.

Note {: .info }

OTP 27 이전에는 용어 동치 연산자에 0.0-0.0을 같은 용어로 취급하는 버그가 있었어요. 부동소수점 0에 대해 동등 비교를 하는 레거시 코드는 is_float/1 가드와 함께 같음(==) 연산자를 쓰도록 옮겨가야 하며, 이를 위한 컴파일러 경고가 추가됐습니다. 경고는 +0.0으로 쓰면 조용해져요. +0.00.0과 같지만 컴파일러가 그 비교가 의도적으로 0.0에 대해 이루어진 것으로 해석하게 합니다.

참고로 이것은 0.0-0.0이 같게 비교되어야 한다고 규정하는 IEEE 754와 호환성을 깨지 않습니다. 숫자로 해석하면(==) 같고, 불투명한 용어로 해석하면(=:=) 같지 않다는 뜻이에요.

예시:

1> 0.0 =:= +0.0.
true
2> 0.0 =:= -0.0.
false
3> +0.0 =:= -0.0.
false
4> +0.0 == -0.0.
true

부동소수점 숫자의 표현 (Representation of Floating-Point Numbers)

부동소수점을 다루다 보면 출력이나 산술 연산에서 기대와 다른 결과를 보게 될 수 있어요. 부동소수점은 2진 시스템에서 고정된 비트 수로 표현되는 반면, 출력되는 부동소수점은 10진 시스템으로 표현되기 때문입니다. 에를랭은 64비트 부동소수점을 사용해요. 다음은 이 현상의 예시입니다:

1> 0.1+0.2.
0.30000000000000004

실수 0.10.2는 부동소수점으로 정확히 표현될 수 없습니다.

1> {36028797018963968.0, 36028797018963968 == 36028797018963968.0,
  36028797018963970.0, 36028797018963970 == 36028797018963970.0}.
{3.602879701896397e16, true,
 3.602879701896397e16, false}.

36028797018963968은 부동소수점 값으로 정확히 표현될 수 있지만, 에를랭의 예쁜 출력기(pretty printer)는 36028797018963968.03.602879701896397e16(=36028797018963970.0)으로 반올림해요. [36028797018963966.0, 36028797018963972.0] 범위의 모든 값이 36028797018963968.0으로 표현되기 때문입니다.

부동소수점과 관련된 문제에 대한 더 많은 정보는 다음을 참고하세요:

돈을 나타낼 때처럼 정확한 십진 분수가 필요하다면, 이를 처리하는 라이브러리를 쓰거나 달러·유로 대신 센트로 계산해 십진 분수가 필요 없게 만드는 걸 권장합니다.

또한 에를랭의 부동소수점은 _Inf_나 _NaN_을 지원하지 않는다는 점에서 IEEE 754 부동소수점과 완전히 일치하지 않아요. NaN, +Inf, _-Inf_를 만드는 어떤 연산도 대신 badarith 예외를 발생시킵니다.

예시:

1> 1.0 / 0.0.
** exception error: an error occurred when evaluating an arithmetic expression
     in operator  '/'/2
        called as 1.0 / 0.0
2> 0.0 / 0.0.
** exception error: an error occurred when evaluating an arithmetic expression
     in operator  '/'/2
        called as 0.0 / 0.0

원자 (Atom)

원자(atom)는 리터럴, 즉 이름을 가진 상수예요. 원자는 소문자로 시작하지 않거나 영숫자 문자, 밑줄(_), @ 외의 문자를 포함하면 단일 따옴표(')로 감싸야 합니다.

예시:

hello
phone_number
name@node
'Monday'
'phone number'

비트 문자열과 바이너리 (Bit Strings and Binaries)

비트 문자열(bit string)은 타입이 지정되지 않은 메모리 영역을 저장하는 데 사용됩니다.

비트 문자열은 비트 문법으로 표현됩니다.

8로 균등하게 나누어 떨어지는 비트 수로 이루어진 비트 문자열을 _바이너리(binary)_라고 해요.

예시:

1> <<10,20>>.
<<10,20>>
2> <<"ABC">>.
<<"ABC">>
3> <<1:1,0:1>>.
<<2:2>>

is_bitstring/1 BIF는 용어가 비트 문자열인지, is_binary/1 BIF는 용어가 바이너리인지를 검사합니다.

예시:

1> is_bitstring(<<1:1>>).
true
2> is_binary(<<1:1>>).
false
3> is_binary(<<42>>).
true

더 많은 예시는 Programming Examples를 참고하세요.

레퍼런스 (Reference)

연결된 노드들 사이에서 유일한 용어예요. 레퍼런스는 make_ref/0 BIF를 호출해서 만듭니다. is_reference/1 BIF는 용어가 레퍼런스인지 검사해요.

예시:

1> Ref = make_ref().
#Ref<0.76482849.3801088007.198204>
2> is_reference(Ref).
true

펀 (Fun)

펀(fun)은 함수형 객체입니다. 펀은 익명 함수를 만들고, 함수 자체를 — 이름이 아니라 — 다른 함수의 인자로 전달할 수 있게 해줘요.

예시:

1> Fun1 = fun (X) -> X+1 end.
#Fun<erl_eval.6.39074546>
2> Fun1(2).
3

is_function/1is_function/2 BIF는 용어가 펀인지 검사합니다.

예시:

1> F = fun() -> ok end.
#Fun<erl_eval.43.105768164>
2> is_function(F).
true
3> is_function(F, 0).
true
4> is_function(F, 1).
false

펀에 대해 더 알아보려면 Fun Expressions를 읽어보세요. 더 많은 예시는 Programming Examples에 있습니다.

포트 식별자 (Port Identifier)

포트 식별자는 에를랭 포트를 식별합니다.

open_port/2는 포트 식별자를 반환합니다. is_port/1 BIF는 용어가 포트 식별자인지 검사해요.

포트에 대해 더 알아보려면 Ports and Port Drivers를 읽어보세요.

Pid

Pid는 프로세스 식별자(process identifier)의 약어예요. 각 프로세스는 자신을 식별하는 Pid를 가집니다. Pid는 연결된 노드에서 살아있는 프로세스들 사이에서 유일합니다. 다만 종료된 프로세스의 Pid는 잠시 후 새 프로세스의 Pid로 재사용될 수 있어요.

self/0 BIF는 호출 프로세스의 Pid를 반환합니다. 새 프로세스를 만들 때 부모 프로세스는 자식 프로세스의 Pid를, spawn/3 BIF를 호출할 때처럼 반환 값을 통해 얻거나, spawn_request/5 BIF를 호출할 때처럼 메시지를 통해 얻을 수 있어요. Pid는 보통 프로세스에 시그널을 보낼 때 사용됩니다. is_pid/1 BIF는 용어가 Pid인지 검사해요.

예시:

-module(m).
-export([loop/0]).

loop() ->
    receive
        who_are_you ->
            io:format("I am ~p~n", [self()]),
            loop()
    end.

1> P = spawn(m, loop, []).
<0.58.0>
2> P ! who_are_you.
I am <0.58.0>
who_are_you

프로세스에 대해 더 알아보려면 Processes를 읽어보세요.

튜플 (Tuple)

튜플은 고정된 개수의 용어를 가진 합성 데이터 타입입니다:

{Term1,...,TermN}

튜플 안의 각 용어 Term을 _요소(element)_라고 해요. 요소의 개수를 튜플의 _크기(size)_라고 합니다.

튜플을 다루는 BIF가 여러 개 있어요.

예시:

1> P = {adam,24,{july,29}}.
{adam,24,{july,29}}
2> element(1,P).
adam
3> element(3,P).
{july,29}
4> P2 = setelement(2,P,25).
{adam,25,{july,29}}
5> tuple_size(P).
3
6> tuple_size({}).
0
7> is_tuple({a,b,c}).
true

맵 (Map)

맵은 가변 개수의 키-값 연관을 가진 합성 데이터 타입입니다:

#{Key1 => Value1, ..., KeyN => ValueN}

맵 안의 각 키-값 연관을 _연관 쌍(association pair)_이라고 해요. 쌍의 키 부분과 값 부분을 _요소_라고 합니다. 연관 쌍의 개수를 맵의 _크기(size)_라고 해요.

맵을 다루는 BIF가 여러 개 있습니다.

예시:

1> M1 = #{name => adam, age => 24, date => {july,29}}.
#{age => 24,date => {july,29},name => adam}
2> maps:get(name, M1).
adam
3> maps:get(date, M1).
{july,29}
4> M2 = maps:update(age, 25, M1).
#{age => 25,date => {july,29},name => adam}
5> map_size(M2).
3
6> map_size(#{}).
0

맵 처리 함수 모음은 STDLIB의 m:maps 모듈에서 찾을 수 있어요.

맵에 대해 더 알아보려면 Map Expressions를 읽어보세요.

Change {: .info }

맵은 Erlang/OTP R17에서 실험적 기능으로 도입됐고, 그 기능들은 Erlang/OTP 18에서 확장되어 완전히 지원됐어요.

리스트 (List)

리스트는 가변 개수의 용어를 가진 합성 데이터 타입입니다.

[Term1,...,TermN]

리스트 안의 각 용어 Term을 _요소_라고 해요. 요소의 개수를 리스트의 _길이(length)_라고 합니다.

형식적으로 리스트는 빈 리스트 []이거나, 머리(head)(첫 번째 요소)와 꼬리(tail)(리스트의 나머지)로 이루어집니다. 꼬리 역시 리스트예요. 후자는 [H|T]로 표현할 수 있습니다. 위의 표기 [Term1,...,TermN]은 리스트 [Term1|[...|[TermN|[]]]]와 동등해요.

예시:

[]는 리스트, 따라서
[c|[]]는 리스트, 따라서
[b|[c|[]]]는 리스트, 따라서
[a|[b|[c|[]]]]는 리스트, 줄여서 [a,b,c]

꼬리가 리스트인 리스트를 _정상 리스트(proper list)_라고도 해요. 꼬리가 리스트가 아닌 리스트, 예를 들어 [a|b]를 갖는 것은 허용됩니다. 다만 이런 유형의 리스트는 실용적 가치가 거의 없어요.

예시:

1> L1 = [a,2,{c,4}].
[a,2,{c,4}]
2> [H|T] = L1.
[a,2,{c,4}]
3> H.
a
4> T.
[2,{c,4}]
5> L2 = [d|T].
[d,2,{c,4}]
6> length(L1).
3
7> length([]).
0

리스트 처리 함수 모음은 STDLIB의 m:lists 모듈에서 찾을 수 있어요.

문자열 (String)

문자열은 큰따옴표(")로 감싸지만, 에를랭에서는 데이터 타입이 아니에요. 대신 문자열 "hello"는 리스트 [$h,$e,$l,$l,$o], 즉 [104,101,108,108,111]의 줄임말입니다.

서로 인접한 두 문자열 리터럴은 하나로 이어집니다. 이것은 컴파일 중에 이루어져요.

예시:

"string" "42"

는 다음와 동등합니다:

"string42"

Change {: .info }

Erlang/OTP 27부터 두 인접한 문자열 리터럴은 공백으로 구분되어야 하며, 그렇지 않으면 문법 오류입니다. 이것은 _삼중 따옴표 문자열(triple-quoted string)_과의 혼동 가능성을 피하기 위한 것이에요.

문자열은 _삼중 따옴표 문자열(triple-quoted string)_로 쓸 수도 있는데, 주변 코드의 들여쓰기를 따라 여러 줄에 걸쳐 _들여쓰기_할 수 있습니다. 또한 이들은 _그대로(verbatim)_라서 이스케이프 시퀀스를 허용하지 않으며, 따라서 큰따옴표 문자를 이스케이프할 필요도 없습니다.

Change {: .info }

삼중 따옴표 문자열은 Erlang/OTP 27에서 추가됐어요. 그 전에는 연속된 3개의 큰따옴표 문자가 다른 의미를 가졌습니다. 삼중 따옴표 문자열이 생기기 전에는 그런 문자 시퀀스를 쓸 이유가 전혀 없었지만, 몇 가지 함정이 있습니다. 이 섹션 끝의 Warning을 참고하세요.

예를 들어, 그대로인 큰따옴표 문자가 있는 경우:

"""
  Line "1"
  Line "2"
  """

이것은 (개행도 허용하는) 일반 단일 따옴표 문자열과 동등합니다:

"Line \"1\"
Line \"2\""

여는 줄과 닫는 줄은 구분자, 즉 """ 문자들을 담아요. 그 사이의 줄들이 내용 줄입니다. 여는 줄의 개행은 문자열 내용으로 간주되지 않고, 마지막 내용 줄의 개행도 마찬가지예요.

들여쓰기는 닫는 줄의 구분자 앞에 오는 공백 문자 시퀀스로 정의됩니다. 그 문자 시퀀스는 모든 내용 줄에서 제거됩니다. 닫는 줄에서는 구분자 앞에 공백만 있을 수 있고, 그 외의 것이 있으면 내용 줄로 간주됩니다.

여는 줄은 구분자 뒤에 공백 외의 어떤 문자도 가질 수 없고, 모든 내용 줄은 정의된 들여쓰기 문자 시퀀스로 시작해야 합니다. 그렇지 않으면 문자열은 문법 오류입니다.

다음은 더 큰 예시입니다:

X = """
      First line starting with two spaces
    Not escaped: "\t \r \xFF" and """

    """

이것은 일반 문자열에 해당합니다:

X = "  First line starting with two spaces
Not escaped: \"\\t \\r \\xFF\" and \"\"\"
"

내용 줄의 시작 부분에 연속된 큰따옴표 문자를 쓰고 싶다면 더 많은 큰따옴표 문자를 구분자로 쓰면 됩니다. 다음은 다섯 개의 큰따옴표 구분자를 사용해 정확히 네 개의 큰따옴표 문자를 포함하는 문자열입니다:

"""""
""""
"""""

이 문자열들은 모두 빈 문자열입니다:

""
"""
"""
"""

  """

Warning {: .warning }

삼중 따옴표 문자열이 추가된 Erlang/OTP 27 이전에는, 문자 시퀀스 """"" "로 해석됐습니다. 즉 뒤따르는 문자열에 빈 문자열을 연결한다는 뜻이었어요. 홀수 개의 큰따옴표 문자로 이루어진 모든 시퀀스가 이런 의미를 가졌습니다.

짝수 개의 큰따옴표 문자는 (빈 문자열에) 연결되는 빈 문자열들의 시퀀스로 해석됐어요.

이런 문자 시퀀스를 쓸 이유는 없었습니다. 하지만 만약 그랬다면 삼중 따옴표 문자열의 도입으로 의미가 바뀌었을 가능성이 큽니다.

컴파일러 전처리기는 Erlang/OTP 26.1에서 3개 이상의 연속 큰따옴표 문자에 대해 경고하도록 패치됐고, Erlang/OTP 26.2에서는 공백 없이 인접한 문자열 리터럴에 대해 경고하도록 개선됐습니다. 이것은 문자열 끝의 같은 문제도 다룹니다.

컴파일러가 그런 경고를 내보내면, 두 번째 따옴표 문자마다 공백을 넣도록 큰따옴표 문자 시퀀스를 바꾸고, 중복 빈 문자열을 제거하거나 하나의 문자열로 쓰세요. 그러면 코드가 더 읽기 쉬워지고 모든 릴리스에서 같은 의미를 갖게 됩니다.

시길 (Sigil)

_시길(sigil)_은 문자열 리터럴에 붙는 접두어입니다. 에를랭에서 데이터 타입은 아니고, 문자열 리터럴을 어떻게 해석할지 나타내는 약식 표기예요. 시길은 크게 두 가지를 제공합니다: UTF-8로 인코딩된 바이너리 문자열을 만드는 간결한 방법, 그리고 (정규식 같은 데 유용한) \ 문자를 이스케이프하지 않아도 되는 그대로(verbatim) 문자열을 쓰는 방법이에요.

시길은 물결 문자(~)로 시작하고 그 뒤에 시길 타입을 정의하는 이름이 따라옵니다.

바로 뒤에 시길 내용이 오는데, 내용 구분자들 사이의 문자 시퀀스입니다. 허용되는 구분자는 시작-끝 구분자 쌍 () [] {} <> 이거나, 시작이자 끝인 구분자인 / | ' " ` #입니다. 삼중 따옴표 문자열 구분자도 사용할 수 있어요.

시길 내용의 문자 이스케이프 규칙은 시길 타입에 따라 달라집니다. 시길 내용이 _그대로(verbatim)_이면 이스케이프 문자가 없습니다. 시길 내용은 끝 구분자를 만나면 그냥 끝나므로, 문자열 내용에 끝 구분자 문자를 넣는 것은 불가능해요. 구분자 집합은 꽤 넉넉해서 대부분의 경우 리터럴 문자열 내용에 없는 끝 구분자를 고를 수 있습니다.

삼중 따옴표 문자열 구분자는 문자열 내용에 있는 것보다 더 많은 따옴표 문자를 끝 구분자로 고를 수 있게 해주므로, 그대로 문자열에서도 줄 시작 부분의 " 문자 시퀀스를 포함한 어떤 내용도 가능하게 합니다.

시길들은 다음과 같아요:

  • ~ - 기본(Vanilla) 시길. UTF-8로 인코딩된 t:binary/0의 줄임말이에요. 이 시길은 문자 이스케이프 규칙에 영향을 주지 않아서, 삼중 따옴표 문자열 구분자를 쓰면 ~B와 같고, 다른 문자열 구분자를 쓰면 ~b와 같습니다.

  • ~b - Binary 시길. 시길 내용에 unicode:characters_to_binary/1을 호출한 것처럼 UTF-8 인코딩된 binary()의 줄임말이에요. 문자 이스케이프 규칙은 ~s와 같습니다.

  • ~B - Verbatim Binary 시길. ~b와 같지만 시길 내용이 그대로(verbatim)입니다.

  • ~s - String 시길. 유니코드 코드포인트 리스트인 [char()]string()의 줄임말이에요. 문자 이스케이프 규칙은 일반 t:string/0과 같습니다. 이 시길을 일반 문자열에 쓰는 건 실질적으로 아무 일도 하지 않아요.

  • ~S - Verbatim String 시길. ~s와 같지만 시길 내용이 그대로(verbatim)입니다. 이 시길을 삼중 따옴표 문자열에 쓰는 건 실질적으로 아무 일도 하지 않아요.

예시:

<<"\"\\µA\""/utf8>> = <<$\",$\\,194,181,$A,$">> =
    ~b"""
        "\\µA"
        """ = ~b'"\\µA"' =
    ~B"""
        "\µA"
        """ = ~B<"\µA"> =
    ~"""
        "\µA"
        """ = ~"\"\\µA\"" = ~/"\\µA"/
[$\",$\\,$µ,$A,$"] =
    ~s"""
        "\\µA"
        """ = ~s"\"\\µA\"" = ~s["\\µA"] =
    ~S"""
        "\µA"
        """ = ~S("\µA") =
    """
        "\µA"
        """ = "\"\\µA\""

인접한 문자열은 컴파일 중에 연결되지만, 시길에는 그게 불가능해요. 시길은 일반적으로 연결될 수 없는 용어로 변환되기 때문입니다. 그래서 "a" "b""ab"와 동등하지만 ~s"a" "b"~s"a" ~s"b"는 문법 오류입니다. 반면 ~s"a" ++ "b""ab"로 평가되는데, ++ 연산자의 두 피연산자가 모두 문자열이기 때문이에요.

Change {: .info }

시길은 Erlang/OTP 27에서 도입됐어요.

레코드 (Record)

레코드는 고정된 개수의 요소를 저장하는 데이터 구조입니다. 이름 붙은 필드를 가지며 C의 struct와 비슷합니다. 다만 레코드는 진짜 데이터 타입이 아니에요. 대신 레코드 표현식은 컴파일 중에 튜플 표현식으로 변환됩니다. 따라서 특별한 조치를 취하지 않으면 셸은 레코드 표현식을 이해하지 못해요. 자세한 내용은 STDLIB의 m:shell 모듈을 참고하세요.

예시:

-module(person).
-export([new/2]).

-record(person, {name, age}).

new(Name, Age) ->
    #person{name=Name, age=Age}.

1> person:new(ernie, 44).
{person,ernie,44}

레코드에 대해 더 알아보려면 Records를 읽어보세요. 더 많은 예시는 Programming Examples에 있습니다.

네이티브 레코드 (Native Record)

네이티브 레코드는 고정된 개수의 요소를 저장하는 데이터 구조예요. 전통적인 튜플 기반 레코드와 비슷하지만, 진짜 데이터 타입이라는 점이 다릅니다.

예시:

-module(person).
-export([new/2]).

-record #person{name, age}.

new(Name, Age) ->
    #person{name=Name, age=Age}.
1> P = person:new(ernie, 44).
#person:person{name = ernie,age = 44}
2> is_record(P).
true
3> is_tuple(P).
false
4> is_map(P).
false

Warning {: .warning }

네이티브 레코드는 Erlang/OTP 29에서 실험적인 것으로 간주됩니다. 즉 그 동작이 바뀔 수 있고, 이를 사용하는 애플리케이션의 갱신이 필요할 수도 있다는 뜻이에요.

Change {: .info }

네이티브 레코드는 Erlang/OTP 29에서 도입됐어요.

네이티브 레코드에 대해 더 알아보려면 Native Records를 읽어보세요.

불리언 (Boolean)

에를랭에는 불리언 데이터 타입이 없습니다. 대신 원자 truefalse가 불리언 값을 나타내는 데 사용돼요. is_boolean/1 BIF는 용어가 불리언인지 검사합니다.

예시:

1> 2 =< 3.
true
2> true or false.
true
3> is_boolean(true).
true
4> is_boolean(false).
true
5> is_boolean(ok).
false

이스케이프 시퀀스 (Escape Sequences)

문자열("로 구분된), 따옴표로 감싼 원자, 그리고 ~b~s 시길의 내용 안에서 다음 이스케이프 시퀀스가 인식됩니다:

Sequence Description
\b Backspace (ASCII code 8)
\d Delete (ASCII code 127)
\e Escape (ASCII code 27)
\f Form Feed (ASCII code 12)
\n Line Feed/Newline (ASCII code 10)
\r Carriage Return (ASCII code 13)
\s Space (ASCII code 32)
\t (Horizontal) Tab (ASCII code 9)
\v Vertical Tab (ASCII code 11)
\XYZ, \YZ, \Z Character with octal representation XYZ, YZ or Z
\xXY Character with hexadecimal representation XY
\x{X...} Character with hexadecimal representation; X... is one or more hexadecimal characters
\^a...\^z \^A...\^Z Control A to control Z
\^@ NUL (ASCII code 0)
\^[ Escape (ASCII code 27)
\^\ File Separator (ASCII code 28)
\^] Group Separator (ASCII code 29)
\^^ Record Separator (ASCII code 30)
\^_ Unit Separator (ASCII code 31)
\^? Delete (ASCII code 127)
\' Single quote
\" Double quote
\\ Backslash

Table: Recognized Escape Sequences

Change {: .info }

Erlang/OTP 26부터 $\^?의 값이 31 대신 127(Delete)로 바뀌었어요. 이전 릴리스는 $\^ 뒤에 어떤 문자든 허용했지만, Erlang/OTP 26부터는 문서화된 문자만 허용됩니다.

삼중 따옴표 문자열 안에서는 이스케이프 시퀀스가 인식되지 않아요. 삼중 따옴표 문자열에 쓸 수 없는 유일한 텍스트는 (공백만 앞에 오는) 줄 시작 부분의 연속된 세 개의 큰따옴표 문자입니다. 이 제한은 문자열 안보다 더 큰따옴표 문자로 문자열 구분자를 쓰면 우회할 수 있어요. 시작 구분자에는 3 이상의 어떤 개수도 허용되고, 끝 구분자는 시작 구분자와 같습니다.

~, ~B 또는 ~S 시길과 함께 삼중 따옴표 문자열 구분자를 쓰면 같은 규칙이 적용되지만, ~b 또는 ~s 시길에서는 위의 일반 문자열 이스케이프 시퀀스가 사용됩니다.

Change {: .info }

삼중 따옴표 문자열과 시길은 Erlang/OTP 27에서 도입됐어요.

타입 변환 (Type Conversions)

타입 변환을 위한 BIF가 여러 개 있습니다.

예시:

1> atom_to_list(hello).
"hello"
2> list_to_atom("hello").
hello
3> binary_to_list(<<"hello">>).
"hello"
4> binary_to_list(<<104,101,108,108,111>>).
"hello"
5> list_to_binary("hello").
<<104,101,108,108,111>>
6> float_to_list(7.0).
"7.00000000000000000000e+00"
7> list_to_float("7.000e+00").
7.0
8> integer_to_list(77).
"77"
9> list_to_integer("77").
77
10> tuple_to_list({a,b,c}).
[a,b,c]
11> list_to_tuple([a,b,c]).
{a,b,c}
12> term_to_binary({a,b,c}).
<<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>
13> binary_to_term(<<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>).
{a,b,c}
14> binary_to_integer(<<"77">>).
77
15> integer_to_binary(77).
<<"77">>
16> float_to_binary(7.0).
<<"7.00000000000000000000e+00">>
17> binary_to_float(<<"7.000e+00">>).
7.0

더 알아보기 (Learn more)