Elixir Language
Списки
Поиск…
Синтаксис
- []
- [1, 2, 3, 4]
- [1, 2] ++ [3, 4] # -> [1,2,3,4]
- hd ([1, 2, 3, 4]) # -> 1
- tl ([1, 2, 3, 4]) # -> [2,3,4]
- [глава | хвост]
- [1 | [2, 3, 4]] # -> [1,2,3,4]
- [1 | [2 | [3 | [4 | []]]]] -> [1,2,3,4]
- 'hello' = [? h,? e,? l,? l,? o]
- keyword_list = [a: 123, b: 456, c: 789]
- keyword_list [: a] # -> 123
Списки ключевых слов
Списки ключевых слов представляют собой списки, в которых каждый элемент в списке является кортежем атома, за которым следует значение.
keyword_list = [{:a, 123}, {:b, 456}, {:c, 789}]
Сокращенное обозначение для написания списков ключевых слов выглядит следующим образом:
keyword_list = [a: 123, b: 456, c: 789]
Списки ключевых слов полезны для создания упорядоченных структур данных пары «ключ-значение», где для данного ключа могут существовать несколько элементов.
Первый элемент в списке ключевых слов для заданного ключа может быть получен следующим образом:
iex> keyword_list[:b]
456
Вариант использования для списков ключевых слов может быть последовательностью запущенных именованных задач:
defmodule TaskRunner do
def run_tasks(tasks) do
# Call a function for each item in the keyword list.
# Use pattern matching on each {:key, value} tuple in the keyword list
Enum.each(tasks, fn
{:delete, x} ->
IO.puts("Deleting record " <> to_string(x) <> "...")
{:add, value} ->
IO.puts("Adding record \"" <> value <> "\"...")
{:update, {x, value}} ->
IO.puts("Setting record " <> to_string(x) <> " to \"" <> value <> "\"...")
end)
end
end
Этот код можно вызвать с таким списком ключевых слов:
iex> tasks = [
...> add: "foo",
...> add: "bar",
...> add: "test",
...> delete: 2,
...> update: {1, "asdf"}
...> ]
iex> TaskRunner.run_tasks(tasks)
Adding record "foo"...
Adding record "bar"...
Adding record "test"...
Deleting record 2...
Setting record 1 to "asdf"...
Списки Char
Строки в Elixir - это «двоичные файлы». Однако в коде Erlang строки традиционно являются «списками символов», поэтому при вызове функций Erlang вам, возможно, придется использовать списки символов вместо обычных строк Elixir.
В то время как обычные строки записываются с помощью двойных кавычек "
, символьные списки записываются с помощью одиночных кавычек '
:
string = "Hello!"
char_list = 'Hello!'
Списки Char - это просто списки целых чисел, представляющие кодовые точки каждого символа.
'hello' = [104, 101, 108, 108, 111]
Строка может быть преобразована в список символов с помощью to_charlist/1
:
iex> to_charlist("hello")
'hello'
И обратное можно сделать с помощью to_string/1
:
iex> to_string('hello')
"hello"
Вызов функции Erlang и преобразование вывода в обычную строку Elixir:
iex> :os.getenv |> hd |> to_string
"PATH=/usr/local/bin:/usr/bin:/bin"
Минусы
Списки в Elixir являются связанными списками. Это означает, что каждый элемент в списке состоит из значения, за которым следует указатель на следующий элемент в списке. Это реализовано в Elixir с использованием cons-ячеек.
Минусы - это простые структуры данных с «левым» и «правильным» значением, или «голова» и «хвост».
A |
символ может быть добавлен до последнего элемента в списке, чтобы обозначить (неправильный) список с заданной головой и хвостом. Ниже приведена единственная ячейка cons с 1
в качестве головы и 2
как хвост:
[1 | 2]
Стандартный синтаксис Elixir для списка на самом деле эквивалентен написанию цепочки вложенных cons-ячеек:
[1, 2, 3, 4] = [1 | [2 | [3 | [4 | []]]]]
Пустой список []
используется как хвост ячейки cons для представления конца списка.
Все списки в Elixir эквивалентны форме [head | tail]
, где head
- это первый элемент списка, а tail
- остальная часть списка, минус голова.
iex> [head | tail] = [1, 2, 3, 4]
[1, 2, 3, 4]
iex> head
1
iex> tail
[2, 3, 4]
Использование [head | tail]
полезно для сопоставления образцов в рекурсивных функциях:
def sum([]), do: 0
def sum([head | tail]) do
head + sum(tail)
end
Списки сопоставлений
map
- функция в функциональном программировании, которая задает список и функцию, возвращает новый список с функцией, применяемой к каждому элементу в этом списке. В Elixir функция map/2
находится в модуле Enum .
iex> Enum.map([1, 2, 3, 4], fn(x) -> x + 1 end)
[2, 3, 4, 5]
Использование альтернативного синтаксиса захвата для анонимных функций:
iex> Enum.map([1, 2, 3, 4], &(&1 + 1))
[2, 3, 4, 5]
Ссылаясь на функцию с синтаксисом захвата:
iex> Enum.map([1, 2, 3, 4], &to_string/1)
["1", "2", "3", "4"]
Перемещение операций с использованием оператора трубы:
iex> [1, 2, 3, 4]
...> |> Enum.map(&to_string/1)
...> |> Enum.map(&("Chapter " <> &1))
["Chapter 1", "Chapter 2", "Chapter 3", "Chapter 4"]
Список рекомендаций
Эликсир не имеет петель. Вместо них для списков есть большие модули Enum
и List
, но есть также List Consrehensions.
Список Пояснения могут быть полезны для:
- создавать новые списки
iex(1)> for value <- [1, 2, 3], do: value + 1
[2, 3, 4]
- фильтрация списков, используя
guard
выражения , но использовать их безwhen
это ключевое слово.
iex(2)> odd? = fn x -> rem(x, 2) == 1 end
iex(3)> for value <- [1, 2, 3], odd?.(value), do: value
[1, 3]
- создать пользовательскую карту, используя
into
ключевого слова:
iex(4)> for value <- [1, 2, 3], into: %{}, do: {value, value + 1}
%{1 => 2, 2=>3, 3 => 4}
Комбинированный пример
iex(5)> for value <- [1, 2, 3], odd?.(value), into: %{}, do: {value, value * value}
%{1 => 1, 3 => 9}
Резюме
Список рекомендаций:
- использует синтаксис
for..do
с дополнительнымиfor..do
после запятых иinto
ключевое слово при возврате другой структуры, чем списки, т. е. карта. - в других случаях возвращают новые списки
- не поддерживает аккумуляторы
- не может прекратить обработку при выполнении определенного условия
-
guard
заявления должны быть первыми, чтобы после того, какfor
и передdo
илиinto
символы. Порядок символов не имеет значения
В соответствии с этими ограничениями List Consrehensions ограничены только для простого использования. В более сложных случаях использование функций из модулей Enum
и List
было бы лучшей идеей.
Переменная списка
iex> [1, 2, 3] -- [1, 3]
[2]
--
удаляет первое вхождение элемента в левом списке для каждого элемента справа.
Список участников
Используйте in
операторе, чтобы проверить, является ли элемент членом списка.
iex> 2 in [1, 2, 3]
true
iex> "bob" in [1, 2, 3]
false
Преобразование списков в карту
Используйте Enum.chunk/2
для группировки элементов в под-списки и Map.new/2
для преобразования его в карту:
[1, 2, 3, 4, 5, 6]
|> Enum.chunk(2)
|> Map.new(fn [k, v] -> {k, v} end)
Даст:
%{1 => 2, 3 => 4, 5 => 6}