Tuple 모듈

Tuple 모듈

Elixir에서 튜플은 여러 값이 담긴 고정 크기 컨테이너예요. 이 모듈은 그런 튜플을 다루기 위한 함수들을 모아 놓은 곳이죠. 튜플을 자주 만나게 되겠지만, 실제로 이 모듈의 함수를 쓸 일은 그리 많지 않아요 — 대부분의 작업은 패턴 매칭과 Kernel의 기본 함수로 해결되거든요.

출처: Tuple (Elixir v1.20.4)

본문

튜플 관련 함수 중 자주 쓰이는 몇 가지는 사실 Kernel에 들어 있어요. 다음을 기억해 두면 돼요.

  • elem/2 - 인덱스로 튜플의 원소에 접근해요
  • put_elem/3 - 인덱스로 튜플에 값을 넣어요
  • tuple_size/1 - 튜플의 원소 개수를 구해요

튜플은 여러 원소를 담는 고정 크기 컨테이너로 설계됐어요. 원소를 자유롭게 추가하고 제거해야 하는 컬렉션이라면 리스트를 쓰는 게 맞아요. 그래서 Enum 함수는 튜플에서는 동작하지 않아요.

튜플은 중괄호로 표현해요.

iex> {}
{}
iex> {1, :two, "three"}
{1, :two, "three"}

튜플은 서로 다른 타입의 원소를 담을 수 있고, 메모리에서는 연속된 공간에 저장돼요. 그래서 특정 원소에 접근하는 데 걸리는 시간은 언제나 일정한 반면(상수 시간), 튜플을 수정하는 일은 얕은 복사(shallow copy)를 만들기 때문에 원소 개수에 비례해서 시간이 걸려요. 데이터를 읽는 용도라면 튜플이 좋고, 끝까지 순회해야 한다면 리스트가 더 유리해요.

튜플은 주로 두 가지 상황에서 쓰여요. 하나는 함수가 여러 값을 반환할 때이고, 다른 하나는 에러 처리를 할 때예요. 예를 들어 File.read/1은 파일 읽기에 성공하면 {:ok, contents}를, 대상 파일이 없다든가 하는 이유로 실패하면 {:error, reason}을 반환해요.

이 모듈에 있는 원소 추가·제거 함수들은 실제로는 좀처럼 쓰이지 않아요. 튜플을 컬렉션처럼 다루겠다는 뜻이 되거든요. 튜플에 원소를 추가해야 한다면, 패턴 매칭으로 기존 튜플의 원소를 꺼낸 뒤 새로운 튜플을 만드는 편이 낫다는 게 Elixir의 권장 방식이에요.

tuple = {:ok, :example}

# 비추천
result = Tuple.insert_at(tuple, 2, %{})

# 권장
{:ok, atom} = tuple
result = {:ok, atom, %{}}

delete_at(tuple, index)

지정한 인덱스의 원소를 튜플에서 제거해요.

@spec delete_at(tuple(), non_neg_integer()) :: tuple()

tuple에서 index 위치에 있는 원소를 지워요. index가 음수이거나 tuple의 길이보다 크거나 같으면 ArgumentError를 던져요. 인덱스는 0부터 시작해요. 이 함수는 컴파일러가 인라인 처리해요.

iex> tuple = {:foo, :bar, :baz}
iex> Tuple.delete_at(tuple, 0)
{:bar, :baz}

duplicate(data, size)

새 튜플을 만들어요.

@spec duplicate(term(), non_neg_integer()) :: tuple()

주어진 data를 모든 위치에 담은, 크기가 size인 튜플을 만들어요. 컴파일러가 인라인 처리해요.

iex> Tuple.duplicate(:hello, 3)
{:hello, :hello, :hello}

insert_at(tuple, index, value)

튜플에 원소를 삽입해요.

@spec insert_at(tuple(), non_neg_integer(), term()) :: tuple()

valuetupleindex 위치에 넣어요. index가 음수이거나 tuple의 길이보다 크면 ArgumentError를 던져요. 인덱스는 0부터 시작해요. 컴파일러가 인라인 처리해요.

iex> tuple = {:bar, :baz}
iex> Tuple.insert_at(tuple, 0, :foo)
{:foo, :bar, :baz}
iex> Tuple.insert_at(tuple, 2, :bong)
{:bar, :baz, :bong}

product(tuple) (since 1.12.0)

튜플 원소들의 곱을 계산해요.

@spec product(tuple()) :: number()

빈 튜플 {}의 곱은 1로 정의돼요.

iex> Tuple.product({255, 255})
65025
iex> Tuple.product({255, 1.0})
255.0
iex> Tuple.product({})
1

sum(tuple) (since 1.12.0)

튜플 원소들의 합을 계산해요.

@spec sum(tuple()) :: number()

빈 튜플 {}의 합은 0으로 정의돼요.

iex> Tuple.sum({255, 255})
510
iex> Tuple.sum({255, 0.0})
255.0
iex> Tuple.sum({})
0

to_list(tuple)

튜플을 리스트로 변환해요.

@spec to_list(tuple()) :: list()

튜플의 모든 원소를 담은 새 리스트를 반환해요. 컴파일러가 인라인 처리해요.

iex> tuple = {:foo, :bar, :baz}
iex> Tuple.to_list(tuple)
[:foo, :bar, :baz]

더 알아보기