Зачем мне использовать карты в эликсире - PullRequest
0 голосов
/ 01 ноября 2019

Я изучал основы Elixir в течение последних нескольких дней, и хотя я не раз читал, что новичкам трудно решить, какие структуры данных использовать, я лично не видел ничего особенного в Картах. и структуры. Под этим я подразумеваю:

  • Чтобы получить доступ к полям на карте, мне всегда нужно вызывать Map.fetch(@map, :field), тогда как в структуре я могу легко получить к ней доступ только с помощью '.'между.

Есть ли причина для использования карт? Или я слеп по какой-то другой важной причине? Потому что необходимость всегда вызывать Map.some_function для работы с картами кажется более многословной, чем просто использование структуры.

Ответы [ 4 ]

3 голосов
/ 01 ноября 2019

Ваши предположения о необходимости использования модуля Map для взаимодействия с картами неверны. Например, в iex:

iex(1)> foo = %{bar: "baz"}
%{bar: "baz"}
iex(2)> foo.bar
"baz"
iex(3)> foo = %{foo | bar: "other"}
%{bar: "other"}

Здесь мы создаем карту, выбираем ключ :bar, затем обновляем значение с "baz" до "other", все с использованием встроенного синтаксиса.

Причиной использования структур является проверка ключей во время компиляции. Например, если мы определяем структуру с ключом foo:

defmodule ExampleStruct do
  defstruct [:foo]
end

, а затем пытаемся создать ее с ключом bar:

iex(1)> %ExampleStruct{bar: "baz"}
** (KeyError) key :bar not found
    (testy) expanding struct: ExampleStruct.__struct__/1
    iex:3: (file)

Мы получаем ошибку, потому что :bar не является допустимым ключом для ExampleStruct. С картой нет проверок на ключи, которые можно добавить.

2 голосов
/ 01 ноября 2019

Структуры - это просто карты с договором о том, какие ключи доступны. Давайте определим структуру.

iex> defmodule Alpha do
...>   defstruct [:a, :b, :c]
...> end

Тогда давайте использовать ее:

iex> %Alpha{a: 3, b: 4, c: 5}
%Alpha{a: 3, b: 4, c: 5}

Давайте создадим похожую карту:

iex> %{a: 3, b: 4, c: 5}
%{a: 3, b: 4, c: 5}

Если мы просто добавим :__struct__ ключ, мы неожиданно получаем структуру:

iex> %{__struct__: Alpha, a: 3, b: 4, c: 5}
%Alpha{a: 3, b: 4, c: 5}

Синтаксис . доступен для любой карты с ключами атома:

iex> user = %{name: "Brett"}
%{name: "Brett"}
iex> user.name
"Brett"

Но если вы используете его для ключа, нена карте вы получите сообщение об ошибке:

iex> user.age
** (KeyError) key :age not found in: %{name: "Brett"}

Если структуры имеют определенный набор ключей, вы можете быть намного увереннее, что ключ, который вас интересует, доступен.

Однако, существует множество ситуаций, когда вы хотите использовать карты другими способами. Они позволяют вам гораздо более эффективный поиск, чем повторение списка в любое время, когда вы хотите что-то найти.

1 голос
/ 02 ноября 2019

лично я не видел ничего особенного в Картах и ​​Структурах

  1. Если вы знаете все ключи, которые будут на вашей карте впередивремя, а затем использовать структуру.

  2. Если на вашей карте необходимо хранить неопределенное количество ключей, используйте карту. Например, если вы читаете файл csv (значения, разделенные запятыми), где в каждой строке есть два значения (потенциальный ключ и значение на карте), но количество строк меняется в файлах, которые вы читаете, илиключи и значения не совпадают в разных файлах, и вы хотите ввести эти пары ключ / значение на карте, тогда вы не сможете использовать структуру.

По умолчанию я бы выбрал карту, затем, если в какой-то более поздний момент вы поймете, что ключи всегда одинаковы для создаваемых вами карт, я бы изменил код для использования структуры.

ДляЕще больше запутайте, в elixir также есть keyword lists, например:

[{:a, 1}, {:b, 2}]

или эквивалентный сокращенный синтаксис:

[a: 1, b: 2]

Elixir предоставляет модуль Keyword для доступа к значениям:

... большинство функций в этом модуле ведут себя точно как словарь, поэтому они работают аналогично функциям, которые вы найдете в модуле Map.

Вы можете использовать клавиатуруперечислите, когда вы хотите, чтобы на карте хранилось более одного значения для одного и того же ключа;или когда вы хотите, чтобы пары ключ / значение были в определенном порядке.

1 голос
/ 01 ноября 2019

Struct - это просто карта под капотом с дополнительным полем под названием __struct__. Когда вы создаете карту, вы не можете заставить пользователя включить определенные поля или предоставить некоторые значения по умолчанию для некоторых полей, но вы можете сделать это с помощью структур. Кроме того, вы можете использовать структуры и протоколы для достижения полиморфизма данных, функция которого будет вызываться в зависимости от типа структуры. Пример сценария может быть, если в вашем приложении есть пользователи, и вы предпочитаете использовать структуру %User{} (пример ниже) с некоторыми обязательными полями, такими как name и surname, вместо того, чтобы полагаться на %{} (map). Таким образом вы можете быть уверены, что при создании пользовательской структуры у вас будут поля name и surname, иначе вы получите ошибку времени компиляции.

defmodule User do
   @enforce_keys [:name, :surname]
   defstruct [:name, :surname]
end 

https://elixir-lang.org/getting-started/structs.html

...