패턴매칭 - Elixir의 할당문

에단(손형규)·2022년 5월 20일

Elixir에서 할당문은 일반적으로 우리가 생각하는 할당문과 다릅니다.

따라서, Elixir를 이해하려면 먼저 Elixir의 할당방법을 이해해야합니다.

일반적인 프로그래밍 언어에서의 등호(=)와 수학에서 쓰이는 등호(=)와 비교해봅시다.

x=a+1 이라는 방정식이 있을때 우리는 x에 a+1의 값을 할당하지 않습니다.
그저 x와 a+1이 같은 값인지를 확인할 뿐입니다.

x의 값을 알고 있다면 a의 값을 알아낼 수 있으며, 반대도 마찬가지 입니다.

Elixir의 등호(=)도 이와 비슷합니다.

(1)Elixir의 등호(=)는 매치연산자

iex> a = 1
1
iex> b = a + 2
3

위의 코드를 보면 일반적으로 변수 a에 정수값 1을 할당 했고, 다음 코드에서 a에 2를 더해서 b에는 3이 할당 되었다고 생각할 수 있습니다.

그러나 Elixir에서 '=' 기호는 다른 언어처럼 값을 할당해주는 '대입 연산자'가 아닙니다.

방정식의 등호(=)처럼 동작하는 매치연산자 입니다.

그럼 대입연산자와 어떻게 다른지 다음의 코드를 보겠습니다.

iex> a = 1
1
iex> 1 = a
1
iex> 2 = a
	** (MatchError) no match of right hand side value: 1

Elixir의 '=' 기호는 할당문이 아니라 단언문처럼 동작합니다.

즉, 먼저 좌변과 우변이 같아 질 방법이 있는지 평가를 합니다.

먼저,,,
코드 첫째줄(a = 1)에서 a가 1과 같아 질 방법이 있는지(매칭될 방법이 있는지) 평가를 합니다.
(중요-*Elixir에서는 변수가 좌변에 있을때만 변숫값을 변경할 수 있습니다.)

매칭을 참으로 만들기 위해서, 현재 값이 없는 a에 정수값 1이 바인딩되고 정상적으로 실행이 됩니다.

코드 둘째줄 (1 = a)에서도 1이 a와 같아질 방법이 있는지 평가를 합니다.

앞에서 이미 a에 1을 바인딩해서, 1과 a는 같아 질 수 있으므로(매칭될 수 있으므로) 문제없이 실행됩니다.

하지만,
코드 셋째줄 (2 = a)에서 2는 a에 바인딩 되어있는 1과 같아지게 할 방법이 없으므로(매칭을 참으로 만들 수 없으므로) 매치에러가 발생하게 됩니다.
(중요-*Elixir에서는 변수가 좌변에 있을때만 변숫값을 변경할 수 있습니다.)

이렇게,,,

Elixir에서는 변수에 값을 할당할때 매치연산자를 사용하여 좌변과 우변이 매칭될 수 있는지 평가한 후 값을 할당합니다.

(2)더 복잡한 매칭

Elixir에서는 리스트를 대괄호와 쉼표를 이용하여 다음과 같이 만듭니다.

[1, 2, 3]

iex> list = [1, 2, 3]
[1, 2, 3]
iex> [a, b, c] = list
[1, 2, 3]
iex> a
1
iex> b
2
iex> c
3

list = [1, 2, 3]은 매칭을 참으로 만들기위해 변수 list에는 [1, 2, 3]이 바인딩 되었습니다.

[a, b, c] = list에서 매치연산자를 사용하여 Elixir는 좌변과 우변을 같게 만들 방법을 찾습니다.

좌변은 변수 a,b,c 세 개를 담은 리스트고, 우변은 1, 2, 3 세 개의 값을 담은 리스트입니다.

따라서 각 변수마다 위치에 맞는 값을 바인딩하면 양변이 같아지게 됩니다.
(a=1,b=2,c=3)

이러한 과정을 패턴매칭이라고 합니다.

패턴(좌변)과 값(우변)의 구조가 서고 같고, 패턴과 값의 각 요소를 짝지을 수 있다면 매칭에 성공하게 됩니다.

패턴매칭의 예를 좀 더 확인해 봅시다.

iex> list = [1, 2, [3, 4, 5]]
[1, 2, [3, 4, 5]]
iex> [a, b, c] = list
[1, 2, [3, 4, 5]]
iex> a
1
iex> b
2
iex> c
[3, 4, 5]

위의 예제에서는 매칭에 성공하기위해 변수 c에 리스트 [3, 4, 5] 가 바인딩 되었습니다.

iex> list = [1, 2, 3]
[1, 2, 3]
iex> [a, 2, c] = list
[1, 2, 3]
iex> a
1
iex> c
3

위의 예제에서는 패턴 안에 있는 리터럴 2는 우변의 같은자리에 있는 값과 매칭되므로, a와 c에는 각각 1과 3의 값이 바인딩되었습니다.

iex> list = [1, 2, 3]
[1, 2, 3]
iex> [a, 1, c] = list
 ** (MatchError) no match of right hand side value: [1, 2, 3]

한편 위의 예제에서는 좌변의 리터럴 1가 우변의 같은 위치의 값인 2와 매칭이 되지않아 에러가 발생하게 됩니다.

(3)언더 스코어(_)로 값 무시하기

언더스코어(_)는 패턴(좌변)에서 변수처럼 동작하지만 주어진 값을 바로 버립니다.

패턴매칭에서 모든 값을 받아들이는 와일드카드로 사용할 수 있습니다.

iex> [a, _, _] = [1, 2, 3]
[1, 2, 3]
iex> a
1
iex> [a, _, _] = ["a", "b", "c"]
["a", "b", "c"]
iex> a
"a"

(4)핀 연산자(^)로 값 고정시키기

iex> a = 1
1
iex> a = 2
2
iex> 2 = a
2
iex> ^a = 3
	** (MatchError) no match of right hand side value: 3
iex> ^a = 2
2

Elixir에서는 기본적으로 좌변에 변수가 있고

매치연산자(=)를 사용하면,

매치연산자가 좌변과 우변을 맞추기위해 변수에 새로운 값을 할당합니다.

그렇다면 좌변에 변수가 있을때, 값을 새로 할당하지않고 (2 = a) 처럼

비교만 하고싶을때는 어떻게 해야할까요?

변수 앞에 핀 연산자(^)를 사용하여 값을 고정시켜,

매치연산자로(=) 값이 서로 맞는지만 비교합니다.

profile
asdasdasdasd

0개의 댓글