Map — Elixir의 키-값 데이터 구조

Map — Elixir의 키-값 데이터 구조

Map은 Elixir에서 "가장 많이 쓰는"(go to) 키-값(key-value) 데이터 구조예요. 어떤 값이든 키가 될 수 있고, 특정 키에 연결된 값을 빠르게 꺼내고 싶을 때 거의 항상 Map을 먼저 떠올리게 되죠.

출처: Map

본문

Map은 %{} 문법으로 만들 수 있고, 키-값 쌍은 key => value처럼 표현해요:

iex> %{}
%{}
iex> %{"one" => :two, 3 => "four"}
%{3 => "four", "one" => :two}

Map 안의 키-값 쌍은 어떤 순서도 따르지 않아요. 그래서 위 예시에서 출력된 Map이 처음 만들었을 때와 순서가 달라 보이는 거예요. 정렬된 구조가 아니라 "연관" 구조라는 점을 그대로 드러내는 부분이죠.

Map은 키의 타입에 아무 제약을 두지 않아요. 어떤 값이든 키가 될 수 있어요. 다만 키-값 구조인 만큼 중복 키는 허용하지 않아요. 키는 정확히 일치하는지 보는 ===/2 연산자로 비교해요. 그리고 리터럴 안에 서로 충돌하는 키가 정의되면 마지막 키가 이겨요.

키-값 쌍의 키가 atom이라면 key: value 단축(shorthand) 문법을 쓸 수 있어요. 다른 여러 특수 형태에서 쓰는 표기와 같은 방식이에요:

iex> %{a: 1, b: 2}
%{a: 1, b: 2}

단축 문법을 =>와 섞어 쓰고 싶다면, 단축 문법이 반드시 마지막에 와야 해요:

iex> %{"hello" => "world", a: 1, b: 2}
%{:a => 1, :b => 2, "hello" => "world"}

Map의 키는 이 모듈의 함수들(Map.get/3, Map.fetch/2 등)이나 Access 모듈이 제공하는 map[] 문법으로 접근할 수 있어요:

iex> map = %{a: 1, b: 2}
iex> Map.fetch(map, :a)
{:ok, 1}
iex> map[:b]
2
iex> map["non_existing_key"]
nil

atom 키라면 map.key 표기를 쓸 수도 있어요. 이때 주의할 점이 있는데, map.keymap:key라는 키가 없으면 KeyError를 일으켜요. 반면 map[:key]는 키가 없으면 그냥 nil을 돌려주죠:

map = %{foo: "bar", baz: "bong"}
map.foo
#=> "bar"
map.non_existing_key
** (KeyError) key :non_existing_key not found in:
...

괄호 피하기

필드에 접근할 때 data.key()처럼 괄호를 붙이지 마세요. 괄호를 쓰면 Elixir는 data가 모듈을 나타내는 atom이라고 해석해서, 그 모듈 안에 key/0 함수가 있는지 호출해 보려고 해요. 그러니까 필드 접근이 아니라 다른 의미로 읽히게 된다는 점을 기억해 두세요.

더 알아보기

  • Map.get/3, Map.fetch/2, Map.fetch!/2, Map.put/3 — 키 접근과 갱신의 기본 함수들
  • Keyword — 키가 atom인 리스트 기반 키-값 구조
  • Struct — Map 위에 이름과 기본값을 얹은 구조체
  • Accessmap[] 문법이 동작하는 방식