3장 얼랭 진짜시작하기

By | 2014/04/10

[markdown]
# 3장 진짜 시작하기

[여기](http://learnyousomeerlang.com/starting-out-for-real) 를 요약 정리한 글임을 알려드립니다.

> 얼랭은 상대적으로 작고 심플한 언어이다.(C가 C++보다는 심플한것 처럼)
> 몇가지 기본적인 데이터 타입을 가지고 있음. 이번장에서는 그것들 대부분을 커버해보겠음.
> 앞으로 당신이 작성하게 될 모든 얼랭 프로그램에 사용될 내용을 다루고 있으니 꼭! 읽기를 강추함.

### 숫자

– 얼랭 쉘에서는, 표현식은 공백(빈칸, 개행등)이 뒤따르면 종료되어져야 함. 그렇지 않으면 실행이 안될것임.
– 표현식을 콤마로 구분가능. 그러나 마지막 것의 결과만 보여질것임.

> 얼랭 쉘을 열어서($ erl) 아래의 것들을 쳐보자.

“`
1> 2 + 15.
17
2> 49 * 100.
4900
3> 1892 – 1472.
420
4> 5 / 2.
2.5
5> 5 div 2.
2
6> 5 rem 2.
1
“`

– 얼랭은 integer와 float를 알아서 잘 처리해준다.
– 나누기를 하고 싶을 때 `div`를 나머지를 구하고 싶을 때 `rem`을 사용하시요.
– 수학 명령들은 평범한 우선순위 규칙을 따름(신경안써도 됨)

“`
7> (50 * 100) – 4999.
1
8> -(50 * 100 – 4999).
-1
9> -50 * (100 – 4999).
244950
“`

– 10진수 이외의 진법을 사용하고 싶으면 `진수#값` 이렇게 쓰면 됨
– 기존의 2,8, 16진수 뿐아니라 15진수 36진수(숫자 + 알파벳26자)까지 사용가능

“`
10> 2#101010.
42
11> 8#0677.
447
12> 16#AE.
174
“`

### 불변변수 (Invariable Variables)

– 얼랭으로 산수만 하고 있을 수 없으니 변수를 배워보세.
– 함수형 언어에서는 변수는 변하는 수이어서는 안됨.
– 변수의 기본적인 행위는 아래의 7개의 표현식을 보시길.
– 변수는 항상 `대문자`로 시작하는 것을 잊지말자

“`
1> One.
* 1: variable ‘One’ is unbound
2> One = 1.
1
3> Un = Uno = One = 1.
1
4> Two = One + One.
2
5> Two = 2.
2
6> Two = Two + 1.
** exception error: no match of right hand side value 3
7> two = 2.
** exception error: no match of right hand side value 2
“`
– 위에 6번을 보면 알겠지만, 변수에는 값을 딱 한번만 할당할 수 있음
– 재할당시에 값이 같으면 암말 안하지만, 값이 다른 경우 얼랭 컴파일러가 불평하는 걸 볼 수 있음.
– 좀 더 얘기하면 `=` 연산자는 값을 할당하는 역활 뿐아니라 값이 같은경우 그 값을 리턴하고 다르면 불평을 하게 하는 기능을 가지고 있음.

“`
8> 47 = 45 + 2.
47
9> 47 = 45 + 3.
** exception error: no match of right hand side value 48
“`

– `=` 연산자는 왼쪽에 있는 변수가 값이 할당되지 않은 경우는 오른쪽의 값을 왼쪽의 변수에 할당함. 왼쪽과 오른쪽의 비교 결과는 success가 되서 그 값을 메모리에 저장함.

– `=`연산자가 하는 이런 행동은 `패턴매칭`이라고 하는 것에 기초를 두고 있고, 많은 함수형 프로그래밍 언어에서 가지고 있음. 얼랭은 `=` 요녀석으로 좀더 유연하고 온전한 자신만의 방법을 제공중.
– 변수는 대문자로 시작해야 하지만, `_` 로 시작해도 됨. 그냥 `_` 한글자만 써도 오케이

“`
10> _ = 14+3.
17
11> _.
* 1: variable ‘_’ is unbound
“`

> 얼랭 쉘에서 변수에 잘못된 값을 설정한 경우 `f(변수명)`을 사용하면 변수 초기화 가능. 근데 이함수는 테스트 환경 그것도 쉘에서만 사용가능하고 실환경에서는 사용불가임.

### 아톰(Atoms)

– 변수가 대문자로 시작하면 안되는 단 한가지 이유는 아톰 때문이다.
– 아톰은 리터럴이고 이름과 값을 갖는다.
– 당신이 보는 대로 얻는다. 더이상은 기대하지 말라.
– `cat`이라는 아톰이 의미하는 것은 “cat” 이다.
– 가지고 놀 수 없고, 바꿀 수 없고, 부술 수 없다.
– 소문자로 시작하는 것은 그냥 아톰이다. 더 이상은 없다.
– 작은 따옴표 `’` 로 감싸지는 아톰은 소문자로 시작하지 않아도 된다.
– 아톰이 주로 사용되기 좋은 곳은 데이터와 타입을 짝을 지어야 되는 경우인데, 눈색깔을 표현하기위 해 `BLUE ->1, BROWN ->2, GREEN -> 3, OTHER -> 4` 이런식으로 했었다면, 그냥 아톰으로 `blue`, `brown`, `green`, `other` 단순히 이렇게 하면된다. 만약에 값과 이름이 연결된 것을 정말로 사용하고 싶은 경우는 4장의 `모듈`에서 찾을 수 있다.

“`
1> atom.
atom
2> atoms_rule.
atoms_rule
3> atoms_rule@erlang.
atoms_rule@erlang
4> ‘Atoms can be cheated!’.
‘Atoms can be cheated!’
5> atom = ‘atom’.
atom
“`

– 아톰은 변하지 않는 값을 전달하는 데에는 정말로 좋은 방법이지만, 너무 많은 아톰을 사용하는 것은 문제가 생긴다. “atom table” 이라는 것에서 아톰을 메모리에 올려두고 사용하게 되는데, 아톰 테이블은 GC의 대상이 아니다.
– 그러므로 아톰은 절대로 동적으로 만들어 내지 말라.
– 아래의 아톰들은 예약어로 이미 사용되고 있음.

“`
after and andalso band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse query receive rem try when xor
“`

### 불린 대수 & 비교 연산자들

“`
1> true and false.
false
2> false or true.
true
3> true xor false.
true
4> not false.
true
5> not (true and true).
false
“`

> `and` 와 `or`은 언제나 연산자 양쪽의 것을 실행한다. 필요한 경우에만 오른쪽의 조건을 판단하고 싶은경우 `andalso`와 `orelse`라는 단축 연산자가 있다.

– 동등과 비동등을 테스트 하는것도 겁나 쉽다. 그런데 다른 언어에서 보던 연산자와는 약간 다르다.

“`
6> 5 =:= 5.
true
7> 1 =:= 0.
false
8> 1 =/= 0.
true
9> 5 =:= 5.0.
false
10> 5 == 5.0.
true
11> 5 /= 5.0.
false
“`

– `==` 대신 `=:=`를 사용
– `!=` 대신 `=/=` 를 사용
– 얼랭은 산술계산에서는 부동소수와 정수를 신경써주지 않는데, 비교를 하면 다르다고 나옴. 이런 경우 사용하는 연산자가 `==`랑 `/=`임
– 비교 연산자는 다른 언어와 동일
– `<` 작다, `>` 크다, `>=` 크거나 같다, `=<` 작거나 같다 - 보통 작거나 같다는 `<=` 이렇게 쓰는데...이건 신택스 에러 발생 `5 + llama`를 실행하면 우째 되나? ``` 12> 5 + llama.
** exception error: bad argument in an arithmetic expression
in operator +/2
called as 5 + llama
“`

– 얼랭은 기본타입을 이상하게 사용하는 것을 안좋아함.

“`
13> 5 =:= true.
false
14> 0 == false.
false
15> 1 < false. true ``` - 얼랭은 다른 타입끼리 비교할 수 있음. - 다른 언어에서는 14는 true이고 15는 false여야 하는데. 얼랭에서는 아니다. 잘 기억해두길! > 각 엘레먼트의 올바른 비교 순서는 다음과 같다.
> `number < atom < reference < fun < port < pid < tuple < list < bit string` > 얼랭을 만든 사람들중 한사람인 조 암스트롱에게 물어보니: “실제적으로 순서는 안중요해요. 그렇지만 전체적인 순서가 잘 정의되어 있다는 건 중요하죠.” 라고 했단다.

### 튜플

– 튜플은 데이터를 조직하는 방법이다.
– 얼랭에서 튜플은 요렇게 적는다. `{Element1, Element2, …, ElementN}`
– 좌표에 대한 튜플을 만든다면 아래와 같이 할 수 있다.

“`
1> X = 10, Y = 4.
4
2> Point = {X,Y}.
{10,4}
“`

– 만약에 Point에서 X값만 필요한 경우는 어떻게 하면되나? => 얼랭에서 값을 변수에 할당할 때 값은 값을 할당을 하는 거면 여러번 할당해도 에러가 안났다는 것을 이용하면 된다. 하기 전에 `f()`로 `X, Y, Point`의 값을 초기화 해줘야함.

“`
3> Point = {4,5}.
{4,5}
4> {X,Y} = Point.
{4,5}
5> X.
4
6> {X,_} = Point.
{4,5}
“`

– 6번 표현식은 익명 변수 `_`를 사용했다. `_`는 항상 할당되어 있지 않다고 여겨지고, 패턴매칭에서 와일드 카드로 사용된다. 튜플의 패턴매칭에서는 좌우의 인자의 숫자가 같아야 한다.

– 튜플은 하나의 값만 다룰 때에도 유용하다.
– 섭씨와 화씨에 대한 값을 가지고 있는 온도를 표현하는 튜플을 만들려면?
“`
9> Temperature = 23.213.
23.213
10> PreciseTemperature = {celsius, 23.213}.
{celsius,23.213}
11> {kelvin, T} = PreciseTemperature.
** exception error: no match of right hand side value {celsius,23.213}
“`

– 11번에서 에러가 났지만 의도한것과 정확히 일치한다. 패턴매칭이 먹혀들었다.
– `=` 연산자로 `{kelvin, T}` 와 `{celsius,23.213}`를 비교했다. 심지어 T는 값이 할당이 되지도 않았다.
– 얼랭은 `celsius`와 `kelvin` 아톰이 다르다고 보았고 에러를 발생시켜서 코드의 실행을 정지 시켰다.
– 하나의 아톰에 하나의 값이 있는 튜플을 `tagged tuple`이라고 부른다.
– 튜플내의 원소는 어떤 타입이어도 상관없다. 심지어 다른 튜플이 들어가도 된다.

“`
12> {point, {X,Y}}.
{point,{4,5}}
“`

### 리스트!

– 의심할 여지 없이 얼랭에서 가장 많이 쓰이는 데이터 타입임.
– 아무거나 담을 수 있다. (숫자, 아톰, 튜플, 다른 리스트)
– `[Element1, Element2, …, ElementN]` 요렇게 사용

“`
1> [1, 2, 3, {numbers,[4,5,6]}, 5.34, atom].
[1,2,3,{numbers,[4,5,6]},5.34,atom]
2> [97, 98, 99].
“abc”
“`

– 2번의 결과는 사람들이 얼랭에서 가장 놀라는 부분임. 왜냐면 아래를 보시라.

“`
3> [97,98,99,4,5,6].
[97,98,99,4,5,6]
4> [233].
“é”
“`

– 얼랭은 리스트안의 숫자중에 글자를 나타내지 않는 숫자가 최소 하나이상 있어야 숫자를 출력한다.
– 얼랭에는 진짜 스트링은 없다!
– 리스트를 두개를 합치려면 `++` 연산자를 사용하고 제거 하려면 `–`연산자를 사용하라

“`
5> [1,2,3] ++ [4,5].
[1,2,3,4,5]
6> [1,2,3,4,5] — [1,2,3].
[4,5]
7> [2,4,2] — [2,4].
[2]
8> [2,4,2] — [2,4,2].
[]
“`

– `++`, `–`는 연산 순서가 오른쪽 우선이다. 오른쪽에서 왼쪽으로 계산된다.

“`
9> [1,2,3] — [1,2] — [3].
[3]
10> [1,2,3] — [1,2] — [2].
[2,3]
“`

– 리스트의 첫번째 엘리먼트는 Head라고 하고, 남은 것들은 Tail이라고 한다. 내장 함수(Built In Functions:BIF)로 그것들을 가져와 보자.

“`
11> hd([1,2,3,4]).
1
12> tl([1,2,3,4]).
[2,3,4]
“`

> 내장함수(BIF)들은 퍼포먼스 향상을 위해 C같이 빠른 언어로 구현되어 있다.

– Head를 더하거나 접근 하는 것은 빠르고, 효과적이다.
– head와 tail을 분리하는 멋진 패턴 매칭이 있는데 바로 이것이다. `[Head|Tail]` 여기 새로운 head를 리스트에 추가하는 예제가 있다.

“`
13> List = [2,3,4].
[2,3,4]
14> NewList = [1|List].
[1,2,3,4]
“`
아래는 리스트로 부터 Head와 Tail을 가르는 예제
“`
15> [Head|Tail] = NewList.
[1,2,3,4]
16> Head.
1
17> Tail.
[2,3,4]
18> [NewHead|NewTail] = Tail.
[2,3,4]
19> NewHead.
2
“`

– `|`는 cons 연산자(컨스트럭터)라고도 한다. 실제로 어떤한 리스트도 cons와 값만 있으면 만들 수 있다.

“`
20> [1 | []].
[1]
21> [2 | [1 | []]].
[2,1]
22> [3 | [2 | [1 | []] ] ].
[3,2,1]
“`

위의 예제는 어떤 리스트도 다음의 공식으로 만들 수 있다는 것을 말해준다.
`[Term1| [Term2 | [… | [TermN]]]]…`
– 리스트는 Head와 그것을 뒤따르는 Tail을 재귀적으로 정의한 것으로 여겨질 수 있다.
– 리스트는 지렁이랑 비슷한다. 머리를 자르면 지렁이가 두마리가 되는 이치이다.

![지렁이](http://learnyousomeerlang.com/static/img/worm.png)
– 얼랭의 리스트는 때때로 헷갈릴 수 있는데, 이 개념에 익숙해지려면 다음 예제를 다 읽어보라.(힌트 : 모두 같은 리스트이다.)

“`
[a, b, c, d]
[a, b, c, d | []]
[a, b | ]
[a, b | ]]
[a | [b | ]]]
[a | [b | ]]]]
“`

– 위의 것이 이해가 되었다면 리스트 컴프리헨션을 다룰 준비가 됐다는 것이다.

> `[1|2]` 이런 방법으로 리스트를 표현 하는 것을 ‘부적합한 리스트’라고 한다. 부적합한 리스트는 패턴매칭은 성공하지만, 얼랭의 표준 함수에서 사용될 때 실패하는데(length()같은거), 얼랭의 함수는 적합한 리스트를 받게 되어 있기 때문이다. 적합한 리스트는 가장 마지막 셀에 빈 리스트를 포함한다. `[2]`이렇게 선언하면 해당 리스트는 자동으로 적합한 리스트로 변환된다. `[1|[2]]`도 잘 동작한다! 부적합한 리스트는 문법적으로는 유효하지만, 아주 많은 제약이 있다.

### 리스트 컴프리헨션 (리스트 조건제시법, 리스트 내포)

– 리스트 컴프리헨션은 리스트를 만들거나 수정하는 방법들이다.
– 리스트를 다루는 다른 방법 보다 프로그램을 짧고 이해하기 쉽게 해주는 방법이다.
– 처음에는 이해하기가 힘들긴한데, 노력을 할 만한 가치가 있다.
– 개념을 집합에서 가져왔다.

다음과 같은 집합 표기가 있다고 하자.
![](http://learnyousomeerlang.com/static/img/set-comprehension.png) x는 실수이고, 자기자신과 자기자신을 제곱한 값이 같은 집합을 의미하는데, 그 결과과 되는 집합은 `{0,1}`이다. 다른 집합 표기의 예제를 보자. 축약해서 `{x: x > 0}` 이라고 쓰겠다. 우리가 원하는 것은 x > 0인 값이다.

– 리스트 컴프리헨션은 다른 집합으로 부터 집합을 만들어낸다. `{2n : n in L}`이라는 집합이 있고, L이라는 리스트가 `{1,2,3,4}`일 때 이것의 얼랭에서의 구현은 아래와 같다.

“`
1> [2*N || N <- [1,2,3,4]]. [2,4,6,8] ``` 수학식과 얼랭의 표기법을 비교해보면 크게 많이 다르지 않다. 중괄호({})는 대괄호([])가 되고 콜론(:)은 두개의 파이프(||)가 되고 'in'이라는 글자는 화살표(<-)가 된다. 단순히 기호만 바꾸는 것으로 같은 로직을 유지할 수 있다. 위의 예에서 `N`은 [1,2,3,4]각 각의 값에 순차적으로 패턴매칭된다. 화살표(<-)는 `=` 연산자와 동일하게 작동하지만, 예외가 발생한 경우 예외를 무시한다. 리스트 컴프리헨션에 불린 값들을 이용해서 제약들을 추가 가능하다. 1부터 10까지의 숫자에서 짝수만 가져오고 싶다면 아래와 같이 할 수 있다. ``` 2> [X || X <- [1,2,3,4,5,6,7,8,9,10], X rem 2 =:= 0]. [2,4,6,8,10] ``` `x rem 2 =:= 0`는 숫자가 짝수인지 체크한다. 좀 더 실용적인 예제로 식당의 메뉴중에 $3와 $10 사이의 메뉴에는 7%의 세금이 붙는 경우를 살펴보자. ``` 3> RestaurantMenu = [{steak, 5.99}, {beer, 3.99}, {poutine, 3.50}, {kitten, 20.99}, {water, 0.00}].
[{steak,5.99},
{beer,3.99},
{poutine,3.5},
{kitten,20.99},
{water,0.0}]
4> [{Item, Price*1.07} || {Item, Price} <- RestaurantMenu, Price >= 3, Price =< 10]. [{steak,6.409300000000001},{beer,4.2693},{poutine,3.745}] ``` 위의 예제로 숫자가 딱떨어지게는 안나왔지만, 얼랭에서의 리스트 컴프리핸션을 다음과 같은 방식으로 사용하면 될 것이라는 감은 올 것이다. `NewList = [Expression || Pattern <- List, Condition1, Condition2, ..., ConditionN]` `Pattern <- List`는 제너레이터 표현이라고 부른다. ``` 5> [X+Y || X <- [1,2], Y <- [2,3]]. [3,4,4,5] ``` - 위의 예제는 `1+2`, `1+3`, `2+2`, `2+3` 이렇게 실행된다. - 리스트 컴프리헨션의 레시피를 좀 더 일반화 할 수 있다. `NewList = [Expression || GeneratorExp1, GeneratorExp2, ..., GeneratorExpN, Condition1, Condition2, ... ConditionM]` - 제너레이터 표현은 패턴매칭과 연결되어서 필터처럼 동작한다는 것을 주의하시라. ``` 6> Weather = [{toronto, rain}, {montreal, storms}, {london, fog},
6> {paris, sun}, {boston, fog}, {vancouver, snow}].
[{toronto,rain},
{montreal,storms},
{london,fog},
{paris,sun},
{boston,fog},
{vancouver,snow}]
7> FoggyPlaces = [X || {X, fog} <- Weather]. [london,boston] ``` - 리스트 'Weather'의 엘리먼트와 {X, fog}가 매칭되지 않아도 그냥 무시한다. `=`이었으면 에러가 발생했을 것이다. ### 비트 문법 - 대부분의 언어에는 숫자, 아톰, 튜플, 리스트, 구조체 등등을 다루는 것을 지원한다. - 그리고 바이너리 데이터를 다루는 것도 대부분 지원한다. - 얼랭은 패턴매칭에서 한단계 더 나아가서 바이너리 데이터를 다루는 것에 대한 추상화를 지원한다. - 비트를 다루는 것은 유니크한 문법을 가지고 있고 처음 보기엔 이상하지만, 비트와 바이트가 일반적으로 어떻게 동작하는지 안다면 이해가 될 것이다. **어렵다면 남은 부분들은 뛰어 넘어도 된다.** 비트 문법은 <<와 >>로 바이너리 데이터를 감싼후, 콤마로 구분된 읽을 수 있는 세그먼트 별로 나눈다. 하나의 세그먼트는 바이너리의 비트의 시퀀스이다.(꼭 바이트로 구분되어야 되는 건 아니지만, 그게 디폴트이다.) 오렌지의 색을은 포토샵이나 이런데서 #RRGGBB형식으로 나타내면 #F09A29 이런식으로 표현 가능하다. 이걸 얼렝으로 표현하면 다음과 같다.

“`
1> Color = 16#F09A29.
15768105
2> Pixel = <>.
<<240,154,41>>
“`

위의 예제는 기본적으로 “바이너리 값 #F09A29을 24비트 공간에 놔주시요.(Red 8비트, Green 8비트, Blue 8비트)”라는 뜻이다. 값은 파일로 쓰는 것도 가능! 파일은 바이너리 파일로 저장되므로 텍스트에디터에서는 이상한 글자로 나오지만, 얼랭에서 다시 읽으면 제대로 <<240,154,41>>이라고 나옴

더 흥미로운 것은 바이너리를 패턴매치로 풀어낼 수 있는(to unpack) 기능이 있다는 것이다.

“`
3> Pixels = <<213,45,132,64,76,32,76,0,0,234,32,15>>.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
4> <> = Pixels.
** exception error: no match of right hand side value <<213,45,132,64,76,32,76, 0,0,234,32,15>>
5> <> = Pixels.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
“`

위의 예제의 3번 명령에서 우리는 4개의 RGB색의 픽셀을 바이너리로 지정했다.
4번 명령에서는 바이너리에서 4개의 데이터로 풀어낼려고 했으나 에러가 발생! 왜냐하면 실제로 12개의 값이 있는데 4개로 받아서 그렇다. 그래서 5번 명령에서 각각의 값이 24비트데이터인것을 얼랭에게 알려줬는데 그것이 바로`Var:24`의 뜻이다. 우리는 하나의 픽셀을 다시 각각의 색으로 풀어낼 수 있다.

“`
6> <> = <>.
<<213,45,132>>
7> R.
213
“`

첫번째 말고 다른것도 다 필요한 경우는? 얼랭은 이런 경우를 위해 더 많은 문법설탕과 패턴매칭을 할 수 있다.

“`
8> <> = Pixels.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
9> R.
213
“`

멋지지 않은가? 얼랭은 한가지 이상의 방법으로 바이너리 세그먼트를 접근한다.
아래의 것은 모두 유효하다.

“`
Value
Value:Size
Value/TypeSpecifierList
Value:Size/TypeSpecifierList
“`

> __Type__
> 가능한 값들 : `integer | float | binary | bytes | bitstring | bits | utf8 | utf16 | utf32`
> 이것은 바이너리 데이터로 사용되는 것을 종류를 말한다. ‘bytes’는 단순히 ‘binary’를 줄여서 부르는 것임을 주의하라. 마찬가지로 ‘bits’는 ‘bitstring’의 줄임말이다. 타입이 없는 경우는 얼랭은 ‘integer’ 타입으로 가정한다.

> __Signedness__
> 가능한 값들 : `signed | unsigned`
> 타입이 integer인 경우에 매칭을 위해 사용되는 것이다. 디폴트는 ‘unsigned’

> __Endianness__
> 가능한 값들 : `big | little | native`
> Endianness는 integer, utf16, utf32, float를 위한 것이다. 시스템이 어떻게 바이너리 데이터를 잃는가와 관계가 있다. 예를 들어 BMP이미지 헤더의 포맷은 4바이트의 인티져로 되어 있다. 파일이 72바이트 인경우 little-endian시스템은 이것을 `<<72,0,0,0>>`으로 나타낸다. 그리고 big-endian은 <<0,0,0,72>>로 나타낸다. 하나는 ’72’로 읽히고 다른 하나는 ‘1207959552’로 읽어진다. 그러므로 올바른 endianness를 잘 체크해야한다. ‘native’옵션은 런타입에 little-endian인지 big-endian인지 선택한다. 디폴트는 ‘big’

> __Unit__
> unit:Integer로 쓰여짐
> 이것은 비트들에서 각 세그먼트의 사이즈를 말한다. 허용범위가 1..256까지인 쎗이고 인티저는 디폴트 1로, float와 bit string은 8비트 바이너리가 디폴트이다. utf8, utf16, uft32는 unit이 필요없다. unit 사이즈는 byte-alignment의 보장에 사용되곤 한다.

TypeSpecifierList는 내장되어 있고 ‘-‘로 구분되는 어트리뷰트이다.

“`
10> <> = <<-44>>.
<<"Ô">>
11> X1.
212
12> <> = <<-44>>.
<<"Ô">>
13> X2.
-44
14> <> = <<-44>>.
<<"Ô">>
15> X2.
-44
16> <> = <<72>>.
<<"H">>
17> N.
72
18> <> = <<72>>.
<<"H">>
19> <> = <<72,0,0,0>>.
<<72,0,0,0>>
20> Y.
72
“`

바이너리 데이터를 읽는 여러가지 방법이 있다는 것을 이제 알았을 것이다. 좀 헷갈리지만, 대부분의 언어에서 제공하는 다른 툴들에 비해서는 아직 많이 심플하다.

표준 바이너리 명령어들(시프트연산, ‘and’, ‘or’, ‘xor’, ‘not’)또한 얼랭에 포함 되어 있다. `bsl`(Bits Shift Left), `bsr`(Bit Shift Right), `band`, `bor`, `bxor`, `bnot`

“`
2#00100 = 2#00010 bsl 1.
2#00001 = 2#00010 bsr 1.
2#10101 = 2#10001 bor 2#00101.
“`

이러한 문법과 일반적인 비트구문을 사용한다면, 바이너리 데이터의 파싱과 패턴매칭은 누워서 떡먹기이다. 어떤 사람은 TCP세그먼트를 다음과 같은 코드로 파싱 하기도 했다.

“`
<> = SomeBinary.
“`

같은 로직을 비디오 인코딩, 이미지, 다른 프로토콜의 적용등등에 사용할 수 있다.

> __사이다를 너무 많이 마시지는 마세요__
얼랭은 C나 C++에 비해서 느리다. 만약에 당신이 참을성이 부족한 사람이라면 얼랭으로 비디오 컨버팅이나 이미지 변환 작업을 하는 것은 좋지 않은 아이디어이다. 그럼에도 불구하고 바이너리 문법은 엄청나게 재미있다. 얼랭은 단지 무거운 수 덩어리들을 다루기에는 좋지 않을 뿐이다.

> 그렇지만 위와 같은 수치처리가 필요하지 않다면 얼랭은 여전히 이벤트 반응성 또는 메세지 전달 (극단적으로 가벼운 아톰도 도움을 준다.) 어플리케이션을 위해서는 어마무시하게 빠르다. 이벤트를 백만분의 일초단위로 처리할 수 있기때문에 소프트한 리얼타임 어플리케이션에 적합하다.

바이너리 표기는 다른 면도 가지고 있는데, 비트문자열이다. 비트문자열은 리스트로 표현하는 문자열과 같고, 언어에 강하게 연결되어 있지만, 비트문자열은 메모리 공간을 좀더 효율적으로 사용할 수 있게해준다. 왜냐하면 리스트로 된 문자열은 링크드리스트로 되어 있지만, 비트 문자열은 C 배열과 비슷하다. 비트 스트링의 문법은 다음과 같다.`<<"this is a bit string!">>` 리스트로 된 문자열에 비해서 메모리 절약 및 패턴 매칭을 통한 조작도 간단하기 때문에 결과적으로 바이너리 스트링을 사용한다.

> `주의` 아톰이 가볍다고 스트링 대신 사용해서는 안된다. 문자열은 쪼갠다든지, 정규식을 활용한든지 해서 여러가지로 다뤄질 수 있지만, 아톰은 그렇게 될 수 없다.

### 바이너리 컴프리헨션

리스트 컴프리헨션이 리스트를 위한 것이듯, 바이너리 컴프리헨션은 비트 문법을 좀 더 짧고 간결하게 하기 위한 것이다. 바이너리 컴프리헨션은 상대적으로 얼랭에서 신기능에 속한다. 그래서 R13B버젼 이전버젼은 모듈을 불러와야한다. 그 이후는 표준으로 포함되어 있다.

“`
1> [ X || <> <= <<1,2,3,4,5>>, X rem 2 == 0].
[2,4]
“`

리스트 컴프리헨션과 다른 점은 `<-`이 `<=`로 바뀌었다는 점과 리스트([])대신 바이너리 (<<>>)를 사용했다는 것 뿐이다. 위에서 RGB값을 각각의 픽셀로 나타내는 것을 연습했었는데, 구조가 커질 수록 유지보수가 힘들어진다. 이럴경우 바이너리 컴프리헨션을 사용하면 좀 더 깔끔해진다.

“`
2> Pixels = <<213,45,132,64,76,32,76,0,0,234,32,15>>.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
3> RGB = [ {R,G,B} || <> <= Pixels ]. [{213,45,132},{64,76,32},{76,0,0},{234,32,15}] ``` 온전한 바이너리 컴프리헨션은 기본적으로 바이너리 데이터를 인티저를 가지고 있는 튜플로 변환시킨다. 또다른 바이너리 컴프리헨션은 정확히 반대의 기능을 한다 ``` 4> << <> || {R,G,B} <- RGB >>.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
“`

결과적으로 생성되는 바이너리는 제너레이터가 바이너리를 리턴할 경우 정확히 사이즈를 명시하지 않으면 안되니 주의하도록 하자.

“`
5> << <> || Bin <- [<<3,7,5,4,7>>] >>.
** exception error: bad argument
6> << <> || Bin <- [<<3,7,5,4,7>>] >>.
<<3,7,5,4,7>>
“`

위와같이 정해진 사이즈를 주고 바이너리 컴프리헨션을 사용할 수도 있다.

> 이글을 쓰는 지금은 바이너리 컴프리헨션은 아직 잘사용되지 않고 문서도 매우 빈약하다. 그러므로 기본적인 동작을 이해하는 것에 더 의미를 두자. 비트 문법에 대해 더 알려면 [얼랭의 스펙](http://user.it.uu.se/~pergu/papers/erlang05.pdf)을 읽어보는 것도 좋다.
[/markdown]