Spec-Zone.ru › Elixir 1.18

Исходный код Access поведение

Доступ к данным структурам по ключу.

Модуль Access определяет поведение для динамического доступа к ключам любого типа в структуре данных с помощью синтаксиса data[key].

Access поддерживает списки ключевых слов (Keyword) и карты (Map) по умолчанию. Ключевые слова поддерживают только атомарные ключи, ключи для карт могут быть любого типа. Оба возвращают nil если ключ не существует:

iex> keywords = [a: 1, b: 2]
iex> keywords[:a]
1
iex> keywords[:c]
nil

iex> map = %{a: 1, b: 2}
iex> map[:a]
1

iex> star_ratings = %{1.0 => "★", 1.5 => "★☆", 2.0 => "★★"}
iex> star_ratings[1.5]
"★☆"

Этот синтаксис очень удобен, так как он может быть вложен произвольно:

iex> keywords = [a: 1, b: 2]
iex> keywords[:c][:unknown]
nil

Это работает, потому что доступ к чему-либо в значении nil, возвращает само nil:

iex> nil[:a]
nil

Карты и структуры

Хотя синтаксис доступа разрешен в картах с помощью map[key], если ваша карта состоит из предварительно определённых атомных ключей, вы должны предпочесть доступ к этим атомным ключам с помощью map.key вместо map[key], так как map.key будет поднимать исключение, если ключ отсутствует (чего не должно происходить, если ключи предварительно определены) или если map является nil.

Аналогично, поскольку структуры являются картами и структуры имеют предварительно определённые ключи, они допускают только синтаксис struct.key и не допускают синтаксис доступа struct[key].

Другими словами, синтаксис map[key] свободный, возвращая nil для отсутствующих ключей, в то время как синтаксис map.key жёсткий, поднимая исключение для значений nil и отсутствующих ключей.

Для устранения этого противоречия Elixir предоставляет функции get_in/1 и get_in/2, которые способны проходить по вложенным структурам данных, даже при наличии nil:

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_in(users["john"].age)
27
iex> get_in(users["unknown"].age)
nil

Обратите внимание, что даже если пользователь не был найден, get_in/1 вернула nil. Вне get_in/1 попытка получить доступ к полю .age в nil приведет к исключению.

Функция get_in/2 идёт ещё дальше, позволяя смешивать различные аксессоры. Например, имея карту пользователя с ключами :name и :languages, вот как получить имена всех языков программирования:

  iex> languages = [
  ...>   %{name: "elixir", type: :functional},
  ...>   %{name: "c", type: :procedural}
  ...> ]
  iex> user = %{name: "john", languages: languages}
  iex> get_in(user, [:languages, Access.all(), :name])
  ["elixir", "c"]

Этот модуль предоставляет удобные функции для обхода других структур, таких как кортежи и списки. Как мы увидим далее, их также можно использовать для обновления вложенных структур данных.

Если вы хотите узнать больше о двойственной природе карт в Elixir, так как они могут быть как структурированными данными, так и хранилищем пар ключ-значение, см. модуль Map.

Обновление вложенных структур данных

Синтаксис доступа также можно использовать с макросами Kernel.put_in/2, Kernel.update_in/2, Kernel.get_and_update_in/2 и Kernel.pop_in/1 для дальнейшего манипулирования значениями во вложенных структурах данных:

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> put_in(users["john"].age, 28)
%{"john" => %{age: 28}, "meg" => %{age: 23}}

Как показано в предыдущем разделе, вы также можете использовать функции Kernel.put_in/3, Kernel.update_in/3, Kernel.pop_in/2 и Kernel.get_and_update_in/3 для предоставления вложенных пользовательских аксессоров. Например, имея карту пользователя с ключами :name и :languages, вот как можно глубоко обойти карту и преобразовать все имена языков в верхний регистр:

iex> languages = [
...>   %{name: "elixir", type: :functional},
...>   %{name: "c", type: :procedural}
...> ]
iex> user = %{name: "john", languages: languages}
iex> update_in(user, [:languages, Access.all(), :name], &String.upcase/1)
%{
  name: "john",
  languages: [
    %{name: "ELIXIR", type: :functional},
    %{name: "C", type: :procedural}
  ]
}

См. функции key/1, key!/1, elem/1 и all/0 для некоторых доступных аксессоров.

Резюме

Типы

access_fun(данные, текущее_значение)
container()
get_and_update_fun(данные, текущее_значение)
get_fun(данные)
ключ()
nil_container()
t()
значение()

Обработчики

fetch(элемент, ключ)

Вызывается для доступа к значению, хранящемуся по ключу key в данном элементе term.

get_and_update(данные, ключ, функция)

Вызывается для доступа к значению по ключу key и одновременного его обновления.

pop(данные, ключ)

Вызывается для удаления значения по ключу key из данной структуры данных.

Функции

all()

Возвращает функцию, которая получает доступ ко всем элементам в списке.

at(индекс)

Возвращает функцию, которая получает доступ к элементу по индексу index (нумерация с нуля) в списке.

at!(индекс)

То же, что и at/1, но поднимает исключение Enum.OutOfBoundsError если заданный индекс вне границ.

elem(индекс)

Возвращает функцию, которая получает доступ к элементу по заданному индексу в кортеже.

fetch(контейнер, ключ)

Возвращает значение для данного ключа в контейнере (карта, список ключевых слов или структура, которая реализует поведение Access).

fetch!(контейнер, ключ)

Аналогично fetch/2, но возвращает значение напрямую или вызывает исключение KeyError, если key не найдено.

filter(функция)

Возвращает функцию, которая получает доступ ко всем элементам списка, которые соответствуют предоставленному предикату.

find(предикат)

Возвращает функцию, которая получает доступ к первому элементу в списке, который соответствует предоставленному предикату.

get(контейнер, ключ, значение_по_умолчанию \\ nil)

Возвращает значение для данного ключа в контейнере (карта, список ключевых слов или структура, которая реализует поведение Access).

get_and_update(контейнер, ключ, функция)

Возвращает и обновляет значение по данному ключу в контейнере (карта, список ключевых слов, структура, которая реализует поведение Access).

key(ключ, значение_по_умолчанию \\ nil)

Возвращает функцию, которая получает доступ к заданному ключу в карте/структуре.

key!(ключ)

Возвращает функцию, которая получает доступ к заданному ключу в карте/структуре.

pop(контейнер, ключ)

Удаляет запись с заданным ключом из контейнера (карта, список ключевых слов или структура, которая реализует поведение Access).

slice(диапазон)

Возвращает функцию, которая получает доступ ко всем элементам в списке, которые находятся в заданном диапазоне.

END_OF_DOCUMENT_MARKER

Типы

access_fun(data, current_value)Source

@type access_fun(data, current_value) ::
  get_fun(data) | get_and_update_fun(data, current_value)

container()Source

@type container() :: keyword() | struct() | map()

get_and_update_fun(data, current_value)Source

@type get_and_update_fun(data, current_value) :: (:get_and_update,
                                            data,
                                            (term() -> term()) ->
                                              {current_value,
                                               new_data :: container()}
                                              | :pop)

get_fun(data)Source

@type get_fun(data) :: (:get, data, (term() -> term()) -> new_data :: container())

key()Source

@type key() :: any()

nil_container()Source

@type nil_container() :: nil

t()Source

@type t() :: container() | nil_container() | any()

value()Source

@type value() :: any()

Обработчики событий

fetch(term, key)Source

@callback fetch(term :: t(), key()) :: {:ok, value()} | :error

Вызывается для доступа к значению, хранящемуся под key в заданном элементе term.

Эта функция должна возвращать {:ok, value}, где value - значение под key, если ключ существует в элементе, или :error если ключ в элементе отсутствует.

Многие функции, определённые в модуле Access, вызывают эту функцию внутри себя. Эта функция также используется при использовании синтаксиса доступа с квадратными скобками (structure[key]). Обработчик fetch/2, реализованный модулем, определяющим структуру structure, вызывается, и если он возвращает {:ok, value}, то возвращается value, или если он возвращает :error, то возвращается nil.

См. реализации Map.fetch/2 и Keyword.fetch/2 для примеров реализации этого обработчика.

get_and_update(data, key, function)Source

@callback get_and_update(data, key(), (value() | nil ->
                               {current_value, new_value :: value()} | :pop)) ::
  {current_value, new_data :: data}
when current_value: value(), data: container()

Вызывается для доступа к значению под key и его одновременного обновления.

Реализация этого обработчика должна вызвать fun со значением под key в переданной структуре data, или с nil если key отсутствует в ней. Эта функция должна вернуть либо {current_value, new_value}, либо :pop.

Если переданная функция возвращает {current_value, new_value}, возвращаемое значение этого обработчика должно быть {current_value, new_data}, где:

  • current_value - извлечённое значение (которое может быть обработано перед возвращением)

  • new_value - новое значение для хранения под key

  • new_data - data после обновления значения key значением new_value.

Если переданная функция возвращает :pop, возвращаемое значение этого обработчика должно быть {value, new_data}, где value - значение под key (или nil, если отсутствует), а new_data - data без key.

См. реализации Map.get_and_update/3 или Keyword.get_and_update/3 для получения дополнительных примеров.

pop(data, key)Source

@callback pop(data, key()) :: {value(), data} when data: container()

Вызывается для "удаления" значения под key из заданной структуры данных.

Если key существует в заданной структуре data, реализация должна вернуть кортеж {value, new_data}, где value - значение, которое было под key, а new_data - term без key.

Если key отсутствует в заданной структуре, должен быть возвращён кортеж {value, data}, где value - значение, определённое реализацией.

См. реализации Map.pop/3 или Keyword.pop/3 для получения дополнительных примеров.

END_OF_DOCUMENT_MARKER

Функции

all()Source

@spec all() :: access_fun(data :: list(), current_value :: list())

Возвращает функцию, которая обращается ко всем элементам в списке.

Возвращаемая функция обычно передаётся в качестве аксессора к Kernel.get_in/2, Kernel.get_and_update_in/3 и аналогичным функциям.

Примеры

iex> list = [%{name: "john"}, %{name: "mary"}]
iex> get_in(list, [Access.all(), :name])
["john", "mary"]
iex> get_and_update_in(list, [Access.all(), :name], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{["john", "mary"], [%{name: "JOHN"}, %{name: "MARY"}]}
iex> pop_in(list, [Access.all(), :name])
{["john", "mary"], [%{}, %{}]}

Вот пример, который обходит список, удаляя чётные числа и умножая нечётные на 2:

iex> require Integer
iex> get_and_update_in([1, 2, 3, 4, 5], [Access.all()], fn num ->
...>   if Integer.is_even(num), do: :pop, else: {num, num * 2}
...> end)
{[1, 2, 3, 4, 5], [2, 6, 10]}

Если обращается к структуре, которая не является списком, возникает ошибка:

iex> get_in(%{}, [Access.all()])
** (RuntimeError) Access.all/0 expected a list, got: %{}

at(index)Source

@spec at(integer()) :: access_fun(data :: list(), current_value :: term())

Возвращает функцию, которая обращается к элементу по index (нумерация с нуля) в списке.

Учитывайте, что поиск по индексу в списках занимает линейное время: чем больше список, тем дольше займёт обращение к его индексу. Поэтому операции, основанные на индексах, обычно избегают в пользу других функций в модуле Enum.

Возвращаемая функция обычно передаётся в качестве аксессора к Kernel.get_in/2, Kernel.get_and_update_in/3 и аналогичным функциям.

Примеры

iex> list = [%{name: "john"}, %{name: "mary"}]
iex> get_in(list, [Access.at(1), :name])
"mary"
iex> get_in(list, [Access.at(-1), :name])
"mary"
iex> get_and_update_in(list, [Access.at(0), :name], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{"john", [%{name: "JOHN"}, %{name: "mary"}]}
iex> get_and_update_in(list, [Access.at(-1), :name], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{"mary", [%{name: "john"}, %{name: "MARY"}]}

at/1 также может использоваться для извлечения элементов из списка или ключа внутри списка:

iex> list = [%{name: "john"}, %{name: "mary"}]
iex> pop_in(list, [Access.at(0)])
{%{name: "john"}, [%{name: "mary"}]}
iex> pop_in(list, [Access.at(0), :name])
{"john", [%{}, %{name: "mary"}]}

Если индекс выходит за пределы, возвращается nil и функция обновления никогда не вызывается:

iex> list = [%{name: "john"}, %{name: "mary"}]
iex> get_in(list, [Access.at(10), :name])
nil
iex> get_and_update_in(list, [Access.at(10), :name], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{nil, [%{name: "john"}, %{name: "mary"}]}

Если обращается к структуре, которая не является списком, возникает ошибка:

iex> get_in(%{}, [Access.at(1)])
** (RuntimeError) Access.at/1 expected a list, got: %{}

at!(index)Source

@spec at!(integer()) :: access_fun(data :: list(), current_value :: term())

Аналогично at/1, за исключением того, что если заданный индекс выходит за пределы, выбрасывается исключение Enum.OutOfBoundsError.

Примеры

iex> get_in([:a, :b, :c], [Access.at!(2)])
:c
iex> get_in([:a, :b, :c], [Access.at!(3)])
** (Enum.OutOfBoundsError) out of bounds error

elem(index)Source

@spec elem(non_neg_integer()) :: access_fun(data :: tuple(), current_value :: term())

Возвращает функцию, которая обращается к элементу по заданному индексу в кортеже.

Возвращаемая функция обычно передаётся в качестве аксессора к Kernel.get_in/2, Kernel.get_and_update_in/3 и аналогичным функциям.

Возвращаемая функция вызывает исключение, если index выходит за пределы.

Обратите внимание, что извлечение элементов из кортежей невозможно и вызывает ошибку.

Примеры

iex> map = %{user: {"john", 27}}
iex> get_in(map, [:user, Access.elem(0)])
"john"
iex> get_and_update_in(map, [:user, Access.elem(0)], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{"john", %{user: {"JOHN", 27}}}
iex> pop_in(map, [:user, Access.elem(0)])
** (RuntimeError) cannot pop data from a tuple

Если обращается к структуре, которая не является кортежем, возникает ошибка:

iex> get_in(%{}, [Access.elem(0)])
** (RuntimeError) Access.elem/1 expected a tuple, got: %{}

fetch(container, key)Source

@spec fetch(container(), term()) :: {:ok, term()} | :error
@spec fetch(nil_container(), any()) :: :error

Извлекает значение для данного ключа в контейнере (словарь, список ключевых слов или структура, реализующая поведение Access).

Возвращает {:ok, value}, где value — это значение под key, если такой ключ существует, или :error если key не найден.

Примеры

iex> Access.fetch(%{name: "meg", age: 26}, :name)
{:ok, "meg"}

iex> Access.fetch([ordered: true, on_timeout: :exit], :timeout)
:error

fetch!(container, key)Source

@spec fetch!(container(), term()) :: term()

То же самое, что fetch/2, но возвращает значение непосредственно или вызывает исключение KeyError, если key не найден.

Примеры

iex> Access.fetch!(%{name: "meg", age: 26}, :name)
"meg"

filter(func)Source

@spec filter((term() -> boolean())) ::
  access_fun(data :: list(), current_value :: list())

Возвращает функцию, которая обращается ко всем элементам списка, соответствующим заданному предикату.

Возвращаемая функция обычно передаётся в качестве аксессора к Kernel.get_in/2, Kernel.get_and_update_in/3 и аналогичным функциям.

Примеры

iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]
iex> get_in(list, [Access.filter(&(&1.salary > 20)), :name])
["francine"]
iex> get_and_update_in(list, [Access.filter(&(&1.salary <= 20)), :name], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{["john"], [%{name: "JOHN", salary: 10}, %{name: "francine", salary: 30}]}

filter/1 также может использоваться для извлечения элементов из списка или ключа внутри списка:

iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]
iex> pop_in(list, [Access.filter(&(&1.salary >= 20))])
{[%{name: "francine", salary: 30}], [%{name: "john", salary: 10}]}
iex> pop_in(list, [Access.filter(&(&1.salary >= 20)), :name])
{["francine"], [%{name: "john", salary: 10}, %{salary: 30}]}

Если совпадений не найдено, возвращается пустой список, и функция обновления никогда не вызывается

iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]
iex> get_in(list, [Access.filter(&(&1.salary >= 50)), :name])
[]
iex> get_and_update_in(list, [Access.filter(&(&1.salary >= 50)), :name], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{[], [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]}

Если предикат не является функцией или имеет неправильную арность, возникает ошибка:

iex> get_in([], [Access.filter(5)])
** (FunctionClauseError) no function clause matching in Access.filter/1

Если обращается к структуре, которая не является списком, возникает ошибка:

iex> get_in(%{}, [Access.filter(fn a -> a == 10 end)])
** (RuntimeError) Access.filter/1 expected a list, got: %{}

find(predicate)Source

@spec find((term() -> as_boolean(term()))) ::
  access_fun(data :: list(), current_value :: term())

Возвращает функцию, которая обращается к первому элементу списка, соответствующему заданному предикату.

Возвращаемая функция обычно передаётся в качестве аксессора к Kernel.get_in/2, Kernel.get_and_update_in/3 и аналогичным функциям.

Примеры

iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]
iex> get_in(list, [Access.find(&(&1.salary > 20)), :name])
"francine"
iex>  get_and_update_in(list, [Access.find(&(&1.salary <= 40)), :name], fn prev ->
...> {prev, String.upcase(prev)}
...>  end)
{"john", [%{name: "JOHN", salary: 10}, %{name: "francine", salary: 30}]}

find/1 также может использоваться для извлечения первого найденного элемента из списка или ключа внутри списка:

iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]
iex> pop_in(list, [Access.find(&(&1.salary <= 40))])
{%{name: "john", salary: 10}, [%{name: "francine", salary: 30}]}

Если совпадений не найдено, возвращается nil, и функция обновления никогда не вызывается

iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]
iex> get_in(list, [Access.find(&(&1.salary >= 50)), :name])
nil
iex> get_and_update_in(list, [Access.find(&(&1.salary >= 50)), :name], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{nil, [%{name: "john", salary: 10}, %{name: "francine", salary: 30}]}

Если предикат не является функцией или имеет неправильную арность, возникает ошибка:

iex> get_in([], [Access.find(5)])
** (FunctionClauseError) no function clause matching in Access.find/1

Если обращается к структуре, которая не является списком, возникает ошибка:

iex>  get_in(%{}, [Access.find(fn a -> a == 10 end)])
** (RuntimeError) Access.find/1 expected a list, got: %{}

get(container, key, default \\ nil)Source

@spec get(container(), term(), term()) :: term()
@spec get(nil_container(), any(), default) :: default when default: var

Получает значение для заданного ключа в контейнере (словарь, список ключевых слов или структура, реализующая поведение Access).

Возвращает значение под key если такой ключ существует, или default если key не найден.

Примеры

iex> Access.get(%{name: "john"}, :name, "default name")
"john"
iex> Access.get(%{name: "john"}, :age, 25)
25

iex> Access.get([ordered: true], :timeout)
nil

get_and_update(container, key, fun)Source

@spec get_and_update(data, key(), (value() | nil ->
                               {current_value, new_value :: value()} | :pop)) ::
  {current_value, new_data :: data}
when data: container(), current_value: var

Получает и обновляет заданный ключ в container (словарь, список ключевых слов, структура, реализующая поведение Access).

Аргумент fun получает значение key (или nil если key не присутствует в container). Он должен вернуть двухэлементный кортеж {current_value, new_value}: значение "get" current_value (полученное значение, которое можно обработать перед возвратом) и новое значение, которое нужно сохранить под key (new_value). fun также может вернуть :pop, что означает, что текущее значение должно быть удалено из контейнера и возвращено.

Возвращаемое значение — двухэлементный кортеж со значением "get", возвращённым fun, и новым контейнером с обновлённым значением под key.

Примеры

iex> Access.get_and_update([a: 1], :a, fn current_value ->
...>   {current_value, current_value + 1}
...> end)
{1, [a: 2]}

key(key, default \\ nil)Source

@spec key(key(), term()) ::
  access_fun(data :: struct() | map(), current_value :: term())

Возвращает функцию, которая обращается к заданному ключу в словаре/структуре.

Возвращаемая функция обычно передаётся в качестве аксессора к Kernel.get_in/2, Kernel.get_and_update_in/3 и аналогичным функциям.

Возвращаемая функция использует значение по умолчанию, если ключ не существует. Это позволяет задавать значения по умолчанию и безопасно проходить по отсутствующим ключам:

iex> get_in(%{}, [Access.key(:user, %{}), Access.key(:name, "meg")])
"meg"

Это также полезно при использовании функций обновления, позволяя нам вводить значения по мере обхода структуры данных для обновлений:

iex> put_in(%{}, [Access.key(:user, %{}), Access.key(:name)], "Mary")
%{user: %{name: "Mary"}}

Примеры

iex> map = %{user: %{name: "john"}}
iex> get_in(map, [Access.key(:unknown, %{}), Access.key(:name, "john")])
"john"
iex> get_and_update_in(map, [Access.key(:user), Access.key(:name)], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{"john", %{user: %{name: "JOHN"}}}
iex> pop_in(map, [Access.key(:user), Access.key(:name)])
{"john", %{user: %{}}}

Если обращается к структуре, которая не является словарем или структурой, возникает ошибка:

iex> get_in([], [Access.key(:foo)])
** (BadMapError) expected a map, got: []

key!(ключ)Source

@spec key!(key()) :: access_fun(data :: struct() | map(), current_value :: term())

Возвращает функцию, которая получает значение по заданному ключу в карте/структуре.

Возвращаемая функция обычно используется как аксессор для Kernel.get_in/2, Kernel.get_and_update_in/3 и подобных функций.

Аналогично key/2, но возвращаемая функция вызывает исключение, если ключ не найден.

Примеры

iex> map = %{user: %{name: "john"}}
iex> get_in(map, [Access.key!(:user), Access.key!(:name)])
"john"
iex> get_and_update_in(map, [Access.key!(:user), Access.key!(:name)], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{"john", %{user: %{name: "JOHN"}}}
iex> pop_in(map, [Access.key!(:user), Access.key!(:name)])
{"john", %{user: %{}}}
iex> get_in(map, [Access.key!(:user), Access.key!(:unknown)])
** (KeyError) key :unknown not found in: %{name: "john"}

Примеры выше можно частично переписать так:

iex> map = %{user: %{name: "john"}}
iex> map.user.name
"john"
iex> get_and_update_in(map.user.name, fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{"john", %{user: %{name: "JOHN"}}}

Однако, с помощью нотации точек невозможно удалить поля, так как предполагается, что эти поля должны существовать. В любом случае, Access.key!/1 полезна, когда ключ не известен заранее и должен быть получен динамически.

Возникает ошибка, если обрабатываемая структура не является картой/структурой:

iex> get_in([], [Access.key!(:foo)])
** (RuntimeError) Access.key!/1 expected a map/struct, got: []

pop(контейнер, ключ)Source

@spec pop(data, key()) :: {value(), data} when data: container()

Удаляет запись с заданным ключом из контейнера (карты, списка ключевых слов или структуры, реализующей поведение Access).

Возвращает кортеж, содержащий значение, связанное с ключом, и обновлённый контейнер. nil возвращается для значения, если ключ отсутствует в контейнере.

Примеры

Для карты:

iex> Access.pop(%{name: "Elixir", creator: "Valim"}, :name)
{"Elixir", %{creator: "Valim"}}

Для списка ключевых слов:

iex> Access.pop([name: "Elixir", creator: "Valim"], :name)
{"Elixir", [creator: "Valim"]}

Для неизвестного ключа:

iex> Access.pop(%{name: "Elixir", creator: "Valim"}, :year)
{nil, %{creator: "Valim", name: "Elixir"}}

slice(диапазон)Source

@spec slice(Range.t()) :: access_fun(data :: list(), current_value :: list())

Возвращает функцию, которая получает все элементы списка, находящиеся в заданном диапазоне.

Диапазон будет нормализован по тем же правилам, что и в Enum.slice/2.

Возвращаемая функция обычно используется как аксессор для Kernel.get_in/2, Kernel.get_and_update_in/3 и подобных функций.

Примеры

iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}, %{name: "vitor", salary: 25}]
iex> get_in(list, [Access.slice(1..2), :name])
["francine", "vitor"]
iex> get_and_update_in(list, [Access.slice(1..3//2), :name], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{["francine"], [%{name: "john", salary: 10}, %{name: "FRANCINE", salary: 30}, %{name: "vitor", salary: 25}]}

slice/1 также может использоваться для извлечения элементов из списка или ключа внутри списка:

iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}, %{name: "vitor", salary: 25}]
iex> pop_in(list, [Access.slice(-2..-1)])
{[%{name: "francine", salary: 30}, %{name: "vitor", salary: 25}], [%{name: "john", salary: 10}]}
iex> pop_in(list, [Access.slice(-2..-1), :name])
{["francine", "vitor"], [%{name: "john", salary: 10}, %{salary: 30}, %{salary: 25}]}

Если совпадение не найдено, возвращается пустой список, и функция обновления никогда не вызывается

iex> list = [%{name: "john", salary: 10}, %{name: "francine", salary: 30}, %{name: "vitor", salary: 25}]
iex> get_in(list, [Access.slice(5..10//2), :name])
[]
iex> get_and_update_in(list, [Access.slice(5..10//2), :name], fn prev ->
...>   {prev, String.upcase(prev)}
...> end)
{[], [%{name: "john", salary: 10}, %{name: "francine", salary: 30}, %{name: "vitor", salary: 25}]}

Возникает ошибка, если обрабатываемая структура не является списком:

iex> get_in(%{}, [Access.slice(2..10//3)])
** (ArgumentError) Access.slice/1 expected a list, got: %{}

Возникает ошибка, если шаг диапазона отрицательный:

iex> get_in([], [Access.slice(2..10//-1)])
** (ArgumentError) Access.slice/1 does not accept ranges with negative steps, got: 2..10//-1

Скачать версию ePub

Создано с помощью ExDoc (v0.36.1) для языка программирования Elixir

© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.18.1/Access.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API