Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Keyword

elixir_livebooks/keyword.livemd

Keyword

A keyword list is a list that consists exclusively of two-element tuples.

The first element of these tuples is known as the key, and it must be an atom. The second element, known as the value, can be any term.

Keywords are mostly used to work with optional values.

Examples

For example, the following is a keyword list:

[{:exit_on_close, true}, {:active, :once}, {:packet_size, 1024}]

Elixir provides a special and more concise syntax for keyword lists:

[exit_on_close: true, active: :once, packet_size: 1024]

The two syntaxes return the exact same value.

A key can be any atom, consisting of Unicode letters, numbers, an underscore or the @ sign. If the key should have any other characters, such as spaces, you can wrap it in quotes:

["exit on close": true]

Wrapping an atom in quotes does not make it a string. Keyword list keys are always atoms. Quotes should only be used when necessary or Elixir will issue a warning.

Duplicate keys and ordering

A keyword may have duplicate keys so it is not strictly a key-value data type. However most of the functions in this module work on a key-value structure and behave similar to the functions you would find in the Map module. For example, Keyword.get/3 will get the first entry matching the given key, regardless if duplicate entries exist. Similarly, Keyword.put/3 and Keyword.delete/2 ensure all duplicate entries for a given key are removed when invoked. Note, however, that keyword list operations need to traverse the whole list in order to find keys, so these operations are slower than their map counterparts.

A handful of functions exist to handle duplicate keys, for example, get_values/2 returns all values for a given key and delete_first/2 deletes just the first entry of the existing ones.

Even though lists preserve the existing order, the functions in Keyword do not guarantee any ordering. For example, if you invoke Keyword.put(opts, new_key, new_value), there is no guarantee for where new_key will be added to (the front, the end or anywhere else).

Given ordering is not guaranteed, it is not recommended to pattern match on keyword lists either. For example, a function such as:

def my_function(some_key: value, another_key: another_value)

will match

my_function(some_key: :foo, another_key: :bar)

but it won’t match

my_function(another_key: :bar, some_key: :foo)

Most of the functions in this module work in linear time. This means that the time it takes to perform an operation grows at the same rate as the length of the list.

Call syntax

When keyword lists are passed as the last argument to a function, the square brackets around the keyword list can be omitted. For example, the keyword list syntax:

String.split("1-0", "-", trim: true, parts: 2)

can be written without the enclosing brackets whenever it is the last argument of a function call:

String.split("1-0", "-", trim: true, parts: 2)

Since tuples, lists and maps are treated similarly to function arguments in Elixir syntax, this property is also available to them:

{1, 2, foo: :bar}
[1, 2, foo: :bar]
%{1 => 2, foo: :bar}

Function delete/2

Deletes the entries in the keyword list under a specific key.

If the key does not exist, it returns the keyword list unchanged. Use delete_first/2 to delete just the first entry in case of duplicate keys.

Examples

Keyword.delete([a: 1, b: 2], :a)
Keyword.delete([a: 1, b: 2, a: 3], :a)
Keyword.delete([b: 2], :a)

Function delete_first/2

Deletes the first entry in the keyword list under a specific key.

If the key does not exist, it returns the keyword list unchanged.

Examples

Keyword.delete_first([a: 1, b: 2, a: 3], :a)
Keyword.delete_first([b: 2], :a)

Function drop/2

Drops the given keys from the keyword list.

Removes duplicate keys from the new keyword list.

Examples

Keyword.drop([a: 1, a: 2], [:a])
Keyword.drop([a: 1, b: 2, c: 3], [:b, :d])
Keyword.drop([a: 1, b: 2, b: 3, c: 3, a: 5], [:b, :d])

Function equal?/2

Checks if two keywords are equal.

Considers two keywords to be equal if they contain the same keys and those keys contain the same values.

Examples

Keyword.equal?([a: 1, b: 2], b: 2, a: 1)
Keyword.equal?([a: 1, b: 2], b: 1, a: 2)
Keyword.equal?([a: 1, b: 2, a: 3], b: 2, a: 3, a: 1)

Comparison between values is done with ===/3, which means integers are not equivalent to floats:

Keyword.equal?([a: 1.0], a: 1)

Function fetch/2

Fetches the value for a specific key and returns it in a tuple.

If the key does not exist, it returns :error.

Examples

Keyword.fetch([a: 1], :a)
Keyword.fetch([a: 1], :b)

Function fetch!/2

Fetches the value for specific key.

If the key does not exist, it raises a KeyError.

Examples

Keyword.fetch!([a: 1], :a)
Keyword.fetch!([a: 1], :b)

Function filter/2

Returns a keyword list containing only the entries from keywords for which the function fun returns a truthy value.

See also reject/2 which discards all entries where the function returns a truthy value.

Examples

Keyword.filter([one: 1, two: 2, three: 3], fn {_key, val} -> rem(val, 2) == 1 end)

Function get/3

Gets the value under the given key.

Returns the default value if key does not exist (nil if no default value is provided).

If duplicate entries exist, it returns the first one. Use get_values/2 to retrieve all entries.

Examples

Keyword.get([], :a)
Keyword.get([a: 1], :a)
Keyword.get([a: 1], :b)
Keyword.get([a: 1], :b, 3)

With duplicate keys:

Keyword.get([a: 1, a: 2], :a, 3)
Keyword.get([a: 1, a: 2], :b, 3)

Function get_and_update/3

Gets the value from key and updates it, all in one pass.

The fun argument receives the value of key (or nil if key is not present) and must return a two-element tuple: the current value (the retrieved value, which can be operated on before being returned) and the new value to be stored under key. The fun may also return :pop, implying the current value shall be removed from the keyword list and returned.

Returns a tuple that contains the current value returned by fun and a new keyword list with the updated value under key.

Examples

Keyword.get_and_update([a: 1], :a, fn current_value ->
  {current_value, "new value!"}
end)
Keyword.get_and_update([a: 1], :b, fn current_value ->
  {current_value, "new value!"}
end)
Keyword.get_and_update([a: 2], :a, fn number ->
  {2 * number, 3 * number}
end)
Keyword.get_and_update([a: 1], :a, fn _ -> :pop end)
Keyword.get_and_update([a: 1], :b, fn _ -> :pop end)

Function get_and_update!/3

Gets the value under key and updates it. Raises if there is no key.

The fun argument receives the value under key and must return a two-element tuple: the current value (the retrieved value, which can be operated on before being returned) and the new value to be stored under key.

Returns a tuple that contains the current value returned by fun and a new keyword list with the updated value under key.

Examples

Keyword.get_and_update!([a: 1], :a, fn current_value ->
  {current_value, "new value!"}
end)
Keyword.get_and_update!([a: 1], :b, fn current_value ->
  {current_value, "new value!"}
end)
Keyword.get_and_update!([a: 1], :a, fn _ ->
  :pop
end)

Function get_lazy/3

Gets the value under the given key.

If key does not exist, lazily evaluates fun and returns its result.

This is useful if the default value is very expensive to calculate or generally difficult to set up and tear down again.

If duplicate entries exist, it returns the first one. Use get_values/2 to retrieve all entries.

Examples

keyword = [a: 1]

fun = fn ->
  # some expensive operation here
  13
end

Keyword.get_lazy(keyword, :a, fun)
Keyword.get_lazy(keyword, :b, fun)

Function get_values/2

Gets all values under a specific key.

Examples

Keyword.get_values([], :a)
Keyword.get_values([a: 1], :a)
Keyword.get_values([a: 1, a: 2], :a)

Function has_key?/2

Returns whether a given key exists in the given keywords.

Examples

Keyword.has_key?([a: 1], :a)
Keyword.has_key?([a: 1], :b)

Function keys/1

Returns all keys from the keyword list.

Keeps duplicate keys in the resulting list of keys.

Examples

Keyword.keys(a: 1, b: 2)
Keyword.keys(a: 1, b: 2, a: 3)
Keyword.keys([{:a, 1}, {"b", 2}, {:c, 3}])

Function keyword?/1

Returns true if term is a keyword list, otherwise false.

When term is a list it is traversed to the end.

Examples

Keyword.keyword?([])
Keyword.keyword?(a: 1)
Keyword.keyword?([{Foo, 1}])
Keyword.keyword?([{}])
Keyword.keyword?([:key])
Keyword.keyword?(%{})

Function merge/2

Merges two keyword lists into one.

Adds all keys, including duplicate keys, given in keywords2 to keywords1, overriding any existing ones.

There are no guarantees about the order of the keys in the returned keyword.

Examples

Keyword.merge([a: 1, b: 2], a: 3, d: 4)
Keyword.merge([a: 1, b: 2], a: 3, d: 4, a: 5)
Keyword.merge([a: 1], [2, 3])

Function merge/3

Merges two keyword lists into one.

Adds all keys, including duplicate keys, given in keywords2 to keywords1. Invokes the given function to solve conflicts.

If keywords2 has duplicate keys, it invokes the given function for each matching pair in keywords1.

There are no guarantees about the order of the keys in the returned keyword.

Examples

Keyword.merge([a: 1, b: 2], [a: 3, d: 4], fn _k, v1, v2 ->
  v1 + v2
end)
Keyword.merge([a: 1, b: 2], [a: 3, d: 4, a: 5], fn :a, v1, v2 ->
  v1 + v2
end)
Keyword.merge([a: 1, b: 2, a: 3], [a: 3, d: 4, a: 5], fn :a, v1, v2 ->
  v1 + v2
end)
Keyword.merge([a: 1, b: 2], [:a, :b], fn :a, v1, v2 ->
  v1 + v2
end)

Function new/0

Returns an empty keyword list, i.e. an empty list.

Examples

Keyword.new()

Function new/1

Creates a keyword list from an enumerable.

Removes duplicate entries and the last one prevails. Unlike Enum.into(enumerable, []), Keyword.new(enumerable) guarantees the keys are unique.

Examples

Keyword.new([{:b, 1}, {:a, 2}])
Keyword.new([{:a, 1}, {:a, 2}, {:a, 3}])

Function new/2

Creates a keyword list from an enumerable via the transformation function.

Removes duplicate entries and the last one prevails. Unlike Enum.into(enumerable, [], fun), Keyword.new(enumerable, fun) guarantees the keys are unique.

Examples

Keyword.new([:a, :b], fn x -> {x, x} end)

Function pop/3

Returns the first value for key and removes all associated entries in the keyword list.

It returns a tuple where the first element is the first value for key and the second element is a keyword list with all entries associated with key removed. If the key is not present in the keyword list, it returns {default, keyword_list}.

If you don’t want to remove all the entries associated with key use pop_first/3 instead, which will remove only the first entry.

Examples

Keyword.pop([a: 1], :a)
Keyword.pop([a: 1], :b)
Keyword.pop([a: 1], :b, 3)
Keyword.pop([a: 1, a: 2], :a)

Function pop!/2

Returns the first value for key and removes all associated entries in the keyword list, raising if key is not present.

This function behaves like pop/3, but raises in case the key is not present in the given keywords.

Examples

Keyword.pop!([a: 1], :a)
Keyword.pop!([a: 1, a: 2], :a)
Keyword.pop!([a: 1], :b)

Function pop_first/3

Returns and removes the first value associated with key in the keyword list.

Keeps duplicate keys in the resulting keyword list.

Examples

Keyword.pop_first([a: 1], :a)
Keyword.pop_first([a: 1], :b)
Keyword.pop_first([a: 1], :b, 3)
Keyword.pop_first([a: 1, a: 2], :a)

Function pop_lazy/3

Lazily returns and removes all values associated with key in the keyword list.

This is useful if the default value is very expensive to calculate or generally difficult to set up and tear down again.

Removes all duplicate keys. See pop_first/3 for removing only the first entry.

Examples

keyword = [a: 1]

fun = fn ->
  # some expensive operation here
  13
end

Keyword.pop_lazy(keyword, :a, fun)
Keyword.pop_lazy(keyword, :b, fun)

Function pop_values/2

Returns all values for key and removes all associated entries in the keyword list.

It returns a tuple where the first element is a list of values for key and the second element is a keyword list with all entries associated with key removed. If the key is not present in the keyword list, it returns {[], keyword_list}.

If you don’t want to remove all the entries associated with key use pop_first/3 instead, which will remove only the first entry.

Examples

Keyword.pop_values([a: 1], :a)
Keyword.pop_values([a: 1], :b)
Keyword.pop_values([a: 1, a: 2], :a)

Function put/3

Puts the given value under the specified key.

If a value under key already exists, it overrides the value and removes all duplicate entries.

Examples

Keyword.put([a: 1], :b, 2)
Keyword.put([a: 1, b: 2], :a, 3)
Keyword.put([a: 1, b: 2, a: 4], :a, 3)

Function put_new/3

Puts the given value under key, unless the entry key already exists.

Examples

Keyword.put_new([a: 1], :b, 2)
Keyword.put_new([a: 1, b: 2], :a, 3)

Function put_new_lazy/3

Evaluates fun and puts the result under key in keyword list unless key is already present.

This is useful if the value is very expensive to calculate or generally difficult to set up and tear down again.

Examples

keyword = [a: 1]

fun = fn ->
  # some expensive operation here
  13
end

Keyword.put_new_lazy(keyword, :a, fun)
Keyword.put_new_lazy(keyword, :b, fun)

Function reject/2

Returns a keyword list excluding the entries from keywords for which the function fun returns a truthy value.

See also filter/2.

Examples

Keyword.reject([one: 1, two: 2, three: 3], fn {_key, val} -> rem(val, 2) == 1 end)

Function replace/3

Puts a value under key only if the key already exists in keywords.

In case a key exists multiple times in the keyword list, it removes later occurrences.

Examples

Keyword.replace([a: 1, b: 2, a: 4], :a, 3)
Keyword.replace([a: 1], :b, 2)

Function replace!/3

Puts a value under key only if the key already exists in keywords.

If key is not present in keywords, it raises a KeyError.

Examples

Keyword.replace!([a: 1, b: 2, a: 3], :a, :new)
Keyword.replace!([a: 1, b: 2, c: 3, b: 4], :b, :new)
Keyword.replace!([a: 1], :b, 2)

Function split/2

Takes all entries corresponding to the given keys and extracts them into a separate keyword list.

Returns a tuple with the new list and the old list with removed keys.

Ignores keys for which there are no entries in the keyword list.

Entries with duplicate keys end up in the same keyword list.

Examples

Keyword.split([a: 1, b: 2, c: 3], [:a, :c, :e])
Keyword.split([a: 1, b: 2, c: 3, a: 4], [:a, :c, :e])

Function take/2

Takes all entries corresponding to the given keys and returns them as a new keyword list.

Preserves duplicate keys in the new keyword list.

Examples

Keyword.take([a: 1, b: 2, c: 3], [:a, :c, :e])
Keyword.take([a: 1, b: 2, c: 3, a: 5], [:a, :c, :e])

Function to_list/1

Returns the keyword list itself.

Examples

Keyword.to_list(a: 1)

Function update/4

Updates the value under key in keywords using the given function.

If the key does not exist, it inserts the given default value. Does not pass the default value through the update function.

Removes all duplicate keys and only updates the first one.

Examples

Keyword.update([a: 1], :a, 13, fn existing_value -> existing_value * 2 end)
Keyword.update([a: 1, a: 2], :a, 13, fn existing_value -> existing_value * 2 end)
Keyword.update([a: 1], :b, 11, fn existing_value -> existing_value * 2 end)

Function update!/3

Updates the value under key using the given function.

Raises KeyError if the key does not exist.

Removes all duplicate keys and only updates the first one.

Examples

Keyword.update!([a: 1, b: 2, a: 3], :a, &(&1 * 2))
Keyword.update!([a: 1, b: 2, c: 3], :b, &(&1 * 2))
Keyword.update!([a: 1], :b, &(&1 * 2))

Function validate/2

Ensures the first argument is a keyword with the given keys and default values.

The second argument must be a list of atoms, specifying a given key, or tuples specifying a key and a default value.

If the keyword list has only the given keys, it returns {:ok, keyword} with default values applied. Otherwise it returns {:error, invalid_keys} with invalid keys.

See also: validate!/2.

Examples

{:ok, result} = Keyword.validate([], one: 1, two: 2)
Enum.sort(result)
{:ok, result} = Keyword.validate([two: 3], one: 1, two: 2)
Enum.sort(result)

If atoms are given, they are supported as keys but do not provide a default value:

{:ok, result} = Keyword.validate([], [:one, two: 2])
Enum.sort(result)
{:ok, result} = Keyword.validate([one: 1], [:one, two: 2])
Enum.sort(result)

Passing unknown keys returns an error:

Keyword.validate([three: 3, four: 4], one: 1, two: 2)

Function validate!/2

Similar to validate/2 but returns the keyword or raises an error.

Examples

Keyword.validate!([], one: 1, two: 2) |> Enum.sort()
Keyword.validate!([two: 3], one: 1, two: 2) |> Enum.sort()

If atoms are given, they are supported as keys but do not provide a default value:

Keyword.validate!([], [:one, two: 2]) |> Enum.sort()
Keyword.validate!([one: 1], [:one, two: 2]) |> Enum.sort()

Passing unknown keys raises an error:

Keyword.validate!([three: 3], one: 1, two: 2)

Function values/1

Returns all values from the keyword list.

Keeps values from duplicate keys in the resulting list of values.

Examples

Keyword.values(a: 1, b: 2)
Keyword.values(a: 1, b: 2, a: 3)