Menengah Exercism • elixir

Keyword Lists

Ringkasan Pelajaran

# Introduction

About

A keyword list is a list of {key, value} tuples. There are two way to write a keyword list:

# concise
[month: "April", year: 2018]

# explicit
[{:month, "April"}, {:year, 2018}]

Keys must be atoms

Not every list of 2-tuples is a keyword list. The keys must be atoms:

Keyword.keyword?([{"month", "April"}])
# => false

If you want to use characters other than letters, numbers, and _ in the key, you need to wrap it in quotes. However, that does not make it a string - it is still an atom.

Keyword.keyword?(["day of week": "Monday"])
# => true

Keys can repeat

Keys in a keyword list can repeat, and the key-value pairs are ordered. When attempting to get a single value under a given key, you will get the first value, and any other values under the same key will be silently ignored.

list = [month: "April", month: "May"]

Keyword.get_values(list, :month)
# => ["April", "May"]

Keyword.get(list, :month)
# => "April"

Keyword lists also support the Access behaviour.

list[:month]
# => "April"

Keyword lists as options

The characteristics of keyword lists made them the default mechanism for passing options to functions in Elixir.

When learning about if, you saw a special shorter syntax:

if age >= 16, do: "beer", else: "no beer"

This may look like if accepts two arguments, but the do: and else: pair is actually a single argument - a keyword list. The same code could be written as:

if age >= 16, [do: "beer", else: "no beer"]
# or
if age >= 16, [{:do, "beer"}, {:else, "no beer"}]

The usage of keyword lists as function options is so common that Elixir allows you to skip the square brackets when the keyword list is the last argument passed to a function.

Since tuples, lists, maps, and others are treated the same as function calls in Elixir syntax, this property is also available to them.

[1, 2, three: 3]
# => [1, 2, {:three, 3}]

Pattern matching

To successfully pattern match on a keyword list using the concise syntax, you would need to specify all of the keys in the correct order. This makes pattern matching an unlikely choice for working with keyword lists. Use the Keyword module or Access behaviour instead.

[month: month] = [month: "April", year: 2018]
# => ** (MatchError) no match of right hand side value: [month: "April", year: 2018]

[year: year, month: month] = [month: "April", year: 2018]
# => ** (MatchError) no match of right hand side value: [month: "April", year: 2018]

Keyword lists vs maps

Keyword listMap
Key typeAtomsAny, can be mixed in one map
Duplicate keysYesNo
Keys orderedYesNo
Accesslist[:key], Keyword.get/2map.key, map[:key], Map.get/2
Access timeLinearLogarithmic
Pattern matchingNot very usefulUseful

Faster access time, flexible key type, and useful pattern matching makes maps the default choice in most cases.

Use keyword lists when you don’t have a lot of data, but need duplicate keys or keys in a specific order.


Originally from Exercism elixir concepts