4 패턴 매칭 - Pattern matching

이 장에서는 Elixir에서 = 연산자는 실제로 매칭 연산자이며, 데이터 구조에 대한 패턴 매칭을 어떻게 사용하는지 살펴 보겠습니다. 마지막으로, 이미 바인딩 된 값에 액세스 할 때 사용하는 핀 연산자 ^ 에 대해 배울것입니다.

In this chapter, we will show how the = operator in Elixir is actually a match operator and how to use it to pattern match inside data structures. Finally, we will learn about the pin operator ^ used to access previously bound values.

4.1 매치 연산자 - The match operator

Elixir에서 변수에 값을 할당하기 위해 = 를 여러 번 사용해 왔습니다.

We have used the = operator a couple times to assign variables in Elixir:

iex> x = 1
1
iex> x
1

Elixir에서 = 연산자는 매치 연산자 라고 합니다. 왜 그런지 봐볼까요.

In Elixir, the = operator is actually called the match operator. Let's see why:

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

1 = x 가 유효한 식이라는것에 주의하십시요, 그리고 왼쪽도 오른쪽도 모두 동일하게 1이기 때문에 일치합니다. 양쪽이 일치하지 않을 경우 MatchError 가 발생합니다.

Notice that 1 = x is a valid expression, and it matched because both the left and right side are equal to 1. When the sides do not match, a MatchError is raised.

변수는 = 의 왼쪽에있을 때만 할당합니다:

A variable can only be assigned on the left side of =:

iex> 1 = unknown
** (RuntimeError) undefined function: unknown/0

unknown 라는 변수는 아직 정의되지 않았기 때문에 Elixir는 당신이 unknown/0 이라는 함수를 호출하고 있다고 생각합니다, 그러나 저런 함수는 없습니다.

Since there is no variable unknown previously defined, Elixir imagined you were trying to call a function named unknown/0, but such a function does not exist.

4.2 패턴 매칭 - Pattern matching

매치 연산자는 간단한 값에 대해 사용할 수 있을뿐 아니라, 복잡한 데이터 타입을 분해하는 데도 사용할 수 있습니다. 예를 들어, 튜플에 대해 패턴 매칭 시킬 수 있습니다:

The match operator is not only used to match against simple values, but it is also useful for destructuring more complex data types. For example, we can pattern match on tuples:

iex> {a, b, c} = {:hello, "world", 42}
{:hello, "world", 42}
iex> a
:hello
iex> b
"world"

패턴 매치는 양쪽이 매치되지 않으면 오류가 발생합니다. 예를 들어 튜플의 크기가 다른 경우:

A pattern match will error in the case that the sides can't match. This is, for example, the case when the tuples have different sizes:

iex> {a, b, c} = {:hello, "world"}
** (MatchError) no match of right hand side value: {:hello, "world"}

그리고 다른 타입을 비교 한 경우:

And also when comparing different types:

iex> {a, b, c} = [:hello, "world", "!"]
** (MatchError) no match of right hand side value: [:hello, "world", "!"]

흥미롭게도, 특정 값에 일치 시킬 수 있습니다. 다음 예제에서는 오른쪽에있는 튜플의 첫 번째 요소가 원자형 :ok값으로 시작하는 경우에만 왼쪽과 일치하는 것입니다:

More interestingly, we can match on specific values. The example below asserts that the left side will only match the right side when the right side is a tuple that starts with the atom :ok:

iex> {:ok, result} = {:ok, 13}
{:ok, 13}
iex> result
13

iex> {:ok, result} = {:error, :oops}
** (MatchError) no match of right hand side value: {:error, :oops}

리스트에도 패턴 매칭 시킬 수 있습니다:

We can pattern match on lists:

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

리스트에서 head와 tail이라는 매칭을 지원 합니다:

A list also supports matching on its own head and tail:

iex> [head | tail] = [1, 2, 3]
[1, 2, 3]
iex> head
1
iex> tail
[2, 3]

함수 hd/1tl/1처럼 head와 tail은 빈리스트에 매칭 시킬 수 없습니다:

Similar to the hd/1 and tl/1 functions, we can't match an empty list with a head and tail pattern:

iex> [h|t] = []
** (MatchError) no match of right hand side value: []

[head | tail]타입은 패턴 매칭에만 사용할 수있는 것이 아니라, 리스트의 헤드에 요소를 추가하는 데 사용할 수 있습니다:

The [head | tail] format is not only used on pattern matching but also for prepending items to a list:

iex> list = [1, 2, 3]
[1, 2, 3]
iex> [0|list]
[0, 1, 2, 3]

패턴 매칭은 튜플과 리스트 등의 데이터 구조를 쉽게 분해 할 수 있습니다. 향후 장에서 설명 하겠지만, 이것은 Elixir에서 재귀의 기초 중 하나이며 Map과 Binary 등의 다른 타입에도 잘 적용 할 수 있습니다.

Pattern matching allows developers to easily destructure data types such as tuples and lists. As we will see in following chapters, it is one of the foundations of recursion in Elixir and applies to other types as well, like maps and binaries.

4.3 핀 연산자 - The pin operator

Elixir에서 변수는 다시 바인딩 될 수 있습니다:

Variables in Elixir can be rebound:

iex> x = 1
1
iex> x = 2
2

핀 연산자 ^ 는 변수의 재 바인딩 뿐만 아니라 이전에 매치 한 값과 매칭시키고 싶은 경우에 사용됩니다:(역자주: 이건 정말 Use Case를 좀 알고 싶네요)

The pin operator ^ can be used when there is no interest in rebinding a variable but rather in matching against its value prior to the match:

iex> x = 1
1
iex> ^x = 2
** (MatchError) no match of right hand side value: 2
iex> {x, ^x} = {2, 1}
{2, 1}
iex> x
2

패턴을 여러 번 사용하는 경우 모든 참조는 같은 패턴에 바인딩 되야 합니다:

Notice that if a variable is mentioned more than once in a pattern, all references should bind to the same pattern:

iex> {x, x} = {1, 1}
1
iex> {x, x} = {1, 2}
** (MatchError) no match of right hand side value: {1, 2}

패턴의 값이 무엇인지 궁금하지 않을 수 있습니다. 그 때는 변수를 _ 로 바인딩 하는 것이 일반적입니다. 예를 들어, 리스트의 헤드값만 알고 싶은경우 tail을 밑줄로 할당합니다:

In some cases, you don't care about a particular value in a pattern. It is a common practice to bind those values to the underscore, _. For example, if only the head of the list matters to us, we can assign the tail to underscore:

iex> [h | _] = [1, 2, 3]
[1, 2, 3]
iex> h
1

_ 는 어디에서도 읽을 수 없는 특별한 값입니다. 읽으려고 하면 바인딩 되지 않았다는 오류가 발생합니다:

The variable _ is special in that it can never be read from. Trying to read from it gives an unbound variable error:

iex> _
** (CompileError) iex:1: unbound variable _

패턴 매칭에 강한 구조를 만들 수도 있지만, 사용 방법에 제한이 있습니다. 예를 들어, 매치 왼쪽에서 함수를 호출 할 수 없습니다. 다음의 예는 유효하지 않습니다:

Although pattern matching allows us to build powerful constructs, its usage is limited. For instance, you cannot make function calls on the left side of a match. The following example is invalid:

iex> length([1,[2],3]) = 3
** (CompileError) iex:1: illegal pattern

패턴 매칭의 소개는 이로써 마치겠습니다. 다음 장에서 보듯이 패턴 매칭은 많은 언어 구조에 가장 일반적인 방법입니다.

This finishes our introduction to pattern matching. As we will see in the next chapter, pattern matching is very common in many language constructs.