Spec-Zone.ru › Elixir 1.9

Список

Функции, работающие со (связанными) списками.

Многие функции, предоставляемые для списков, которые реализуют протокол Enumerable, находятся в модуле Enum.

Кроме того, следующие функции и операторы для списков находятся в Kernel:

  • ++/2
  • --/2
  • hd/1
  • tl/1
  • in/2
  • length/1

Списки в Elixir задаются в квадратных скобках:

iex> [1, "two", 3, :four]
[1, "two", 3, :four]

Два списка могут быть конкатенированы и вычтены с помощью операторов Kernel.++/2 и Kernel.--/2:

iex> [1, 2, 3] ++ [4, 5, 6]
[1, 2, 3, 4, 5, 6]
iex> [1, true, 2, false, 3, true] -- [true, false]
[1, 2, 3, true]

Списки в Elixir фактически являются связанными списками, что означает, что они внутренне представлены парами, содержащими голову и хвост списка:

iex> [head | tail] = [1, 2, 3]
iex> head
1
iex> tail
[2, 3]

Аналогично, мы могли бы записать список [1, 2, 3] используя только такие пары (называемые ячейками конс):

iex> [1 | [2 | [3 | []]]]
[1, 2, 3]

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

iex> [1 | [2 | [3 | 4]]]
[1, 2, 3 | 4]

Хотя несобственные списки обычно избегают, они используются в некоторых особых случаях, таких как сущности iodata и chardata (см. модуль IO).

Благодаря представлению на основе ячеек конс, добавление элемента в начало списка всегда выполняется быстро (постоянное время), в то время как добавление в конец становится медленнее по мере увеличения размера списка (линейное время):

iex> list = [1, 2, 3]
iex> [0 | list] # fast
[0, 1, 2, 3]
iex> list ++ [4] # slow
[1, 2, 3, 4]

Большинство функций в этом модуле работают за линейное время. Это означает, что время выполнения операции растет с такой же скоростью, что и длина списка. Например, length/1 и last/1 будут выполняться за линейное время, потому что им нужно пройти по каждому элементу списка, но first/1 будет выполняться за постоянное время, потому что ей нужен только первый элемент.

Список символов

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

  • быть в диапазоне 0..0x10FFFF (0..1_114_111);
  • и быть вне диапазона 0xD800..0xDFFF (55_296..57_343), который в Unicode зарезервирован для пар суррогатов UTF-16.

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

iex> 'héllo'
[104, 233, 108, 108, 111]

В частности, списки символов будут напечатаны по умолчанию в одинарных кавычках, если они содержат только печатаемые символы ASCII:

iex> 'abc'
'abc'

Причина такого поведения заключается в лучшей поддержке библиотек Erlang, которые могут возвращать текст как списки символов вместо строк Elixir. Одним из примеров таких функций является Application.loaded_applications/0:

Application.loaded_applications()
#=>  [
#=>    {:stdlib, 'ERTS  CXC 138 10', '2.6'},
#=>    {:compiler, 'ERTS  CXC 138 10', '6.0.1'},
#=>    {:elixir, 'elixir', '1.0.0'},
#=>    {:kernel, 'ERTS  CXC 138 10', '4.1'},
#=>    {:logger, 'logger', '1.0.0'}
#=>  ]

Можно проверить, состоит ли список только из печатаемых символов ASCII с помощью ascii_printable?/2.

Несобственные списки никогда не считаются списками символов.

END_OF_DOCUMENT_MARKER

Краткое описание

Функции

ascii_printable?(list, limit \\ :infinity)

Проверяет, является ли list списком символов, содержащим только печатаемые символы ASCII.

delete(list, element)

Удаляет заданный element из list. Возвращает новый список без элемента.

delete_at(list, index)

Создаёт новый список, удалив значение по указанному index.

duplicate(elem, n)

Дублирует заданный элемент n раз в списке.

first(list)

Возвращает первый элемент в list или nil, если list пустой.

flatten(list)

Разворачивает данный list вложенных списков.

flatten(list, tail)

Разворачивает данный list вложенных списков. Список tail будет добавлен в конец развёрнутого списка.

foldl(list, acc, fun)

Складывает (сводит) данный список слева с помощью функции. Требуется аккумулирующая переменная.

foldr(list, acc, fun)

Складывает (сводит) данный список справа с помощью функции. Требуется аккумулирующая переменная.

improper?(list)

Возвращает true если list является несобственным списком. В противном случае возвращает false.

insert_at(list, index, value)

Возвращает список с value вставленным по указанному index.

keydelete(list, key, position)

Принимает list кортежей и удаляет первый кортеж, где элемент в position соответствует заданному key. Возвращает новый список.

keyfind(list, key, position, default \\ nil)

Принимает список кортежей и возвращает первый кортеж, где элемент в position в кортеже соответствует заданному key.

keymember?(list, key, position)

Принимает список кортежей и возвращает true если существует кортеж, где элемент в position в кортеже соответствует заданному key.

keyreplace(list, key, position, new_tuple)

Принимает список кортежей и, если идентифицированный элемент по key в position существует, заменяет его на new_tuple.

keysort(list, position)

Принимает список кортежей и сортирует элементы в position кортежей. Сортировка стабильная.

keystore(list, key, position, new_tuple)

Принимает list кортежей и заменяет элемент, идентифицируемый по key в position, на new_tuple.

keytake(list, key, position)

Принимает list кортежей и возвращает первый кортеж, где элемент в position в кортеже соответствует заданному key, а также list без найденного кортежа.

last(list)

Возвращает последний элемент в list или nil, если list пустой.

myers_difference(list1, list2)

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

myers_difference(list1, list2, diff_script)

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

pop_at(list, index, default \\ nil)

Возвращает и удаляет значение по указанному index в list.

replace_at(list, index, value)

Возвращает список со значением, заменённым по указанному index.

starts_with?(list, prefix)

Возвращает true если list начинается с заданного prefix списка; в противном случае возвращает false.

to_atom(charlist)

Преобразует список символов в атом.

to_charlist(list)

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

to_existing_atom(charlist)

Преобразует список символов в существующий атом. Вызывает исключение ArgumentError, если атом не существует.

to_float(charlist)

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

to_integer(charlist)

Возвращает целое число, текстовое представление которого charlist.

to_integer(charlist, base)

Возвращает целое число, текстовое представление которого charlist в системе счисления base.

to_string(list)

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

to_tuple(list)

Преобразует список в кортеж.

update_at(list, index, fun)

Возвращает список со значением, обновлённым по указанному index.

wrap(term)

Оборачивает term в список, если это не список.

zip(list_of_lists)

Объединяет соответствующие элементы из каждого списка в list_of_lists.

END_OF_DOCUMENT_MARKER

Функции

ascii_printable?(list, limit \\ :infinity)

Характеристики

ascii_printable?(list(), 0) :: true
ascii_printable?([], limit) :: true when limit: :infinity | pos_integer()
ascii_printable?([...], limit) :: boolean()
when limit: :infinity | pos_integer()

Проверяет, является ли list списком символов, состоящим только из печатных символов ASCII.

Принимает необязательный limit в качестве второго аргумента. ascii_printable?/2 проверяет печатность списка только до limit.

Печатный список символов в Elixir содержит только печатные символы в стандартной семибитной кодировке ASCII, которые являются символами от 32 до 126 в десятичной нотации, плюс следующие управляющие символы:

  • ?\a - Звонок
  • ?\b - Возврат на одну позицию назад
  • ?\t - Горизонтальная табуляция
  • ?\n - Перевод строки
  • ?\v - Вертикальная табуляция
  • ?\f - Форматор страницы
  • ?\r - Возврат каретки
  • ?\e - Эскейп

Для получения дополнительной информации ознакомьтесь с разделом Character groups в статье Википедии о ASCII стандарте.

Примеры

iex> List.ascii_printable?('abc')
true

iex> List.ascii_printable?('abc' ++ [0])
false

iex> List.ascii_printable?('abc' ++ [0], 2)
true

Неправильные списки не являются печатными, даже если они состоят только из символов ASCII:

iex> List.ascii_printable?('abc' ++ ?d)
false

delete(list, element)

Характеристики

delete([], any()) :: []
delete([...], any()) :: list()

Удаляет указанный element из list. Возвращает новый список без элемента.

Если element встречается более одного раза в list, удаляется только первое вхождение.

Примеры

iex> List.delete([:a, :b, :c], :a)
[:b, :c]

iex> List.delete([:a, :b, :c], :d)
[:a, :b, :c]

iex> List.delete([:a, :b, :b, :c], :b)
[:a, :b, :c]

iex> List.delete([], :b)
[]

delete_at(list, index)

Характеристики

delete_at(list(), integer()) :: list()

Создает новый список, удаляя значение по указанному index.

Отрицательные индексы указывают смещение от конца list. Если index выходит за пределы, возвращается исходный list.

Примеры

iex> List.delete_at([1, 2, 3], 0)
[2, 3]

iex> List.delete_at([1, 2, 3], 10)
[1, 2, 3]

iex> List.delete_at([1, 2, 3], -1)
[1, 2]

duplicate(elem, n)

Характеристики

duplicate(any(), 0) :: []
duplicate(elem, pos_integer()) :: [elem, ...] when elem: var

Дублирует заданный элемент n раз в списке.

n — целое число, большее или равное 0.

Если n равно 0, возвращается пустой список.

Примеры

iex> List.duplicate("hello", 0)
[]

iex> List.duplicate("hi", 1)
["hi"]

iex> List.duplicate("bye", 2)
["bye", "bye"]

iex> List.duplicate([1, 2], 3)
[[1, 2], [1, 2], [1, 2]]

first(list)

Характеристики

first([]) :: nil
first([elem, ...]) :: elem when elem: var

Возвращает первый элемент в list или nil, если list пустой.

Примеры

iex> List.first([])
nil

iex> List.first([1])
1

iex> List.first([1, 2, 3])
1

flatten(list)

Характеристики

flatten(deep_list) :: list() when deep_list: [any() | deep_list]

Сглаживает заданный list вложенных списков.

Элементы пустых списков отбрасываются.

Примеры

iex> List.flatten([1, [[2], 3]])
[1, 2, 3]

iex> List.flatten([[], [[], []]])
[]

flatten(list, tail)

Характеристики

flatten(deep_list, [elem]) :: [elem]
when deep_list: [elem | deep_list], elem: var

Сглаживает заданный list вложенных списков. Список tail будет добавлен в конец сглаженного списка.

Элементы пустых списков из list отбрасываются, но не из tail.

Примеры

iex> List.flatten([1, [[2], 3]], [4, 5])
[1, 2, 3, 4, 5]

iex> List.flatten([1, [], 2], [3, [], 4])
[1, 2, 3, [], 4]

foldl(list, acc, fun)

Характеристики

foldl([elem], acc, (elem, acc -> acc)) :: acc when elem: var, acc: var

Складывает (сокращает) заданный список слева с помощью функции. Требуется накопитель.

Примеры

iex> List.foldl([5, 5], 10, fn x, acc -> x + acc end)
20

iex> List.foldl([1, 2, 3, 4], 0, fn x, acc -> x - acc end)
2

foldr(list, acc, fun)

Характеристики

foldr([elem], acc, (elem, acc -> acc)) :: acc when elem: var, acc: var

Складывает (сокращает) заданный список справа с помощью функции. Требуется накопитель.

Примеры

iex> List.foldr([1, 2, 3, 4], 0, fn x, acc -> x - acc end)
-2

improper?(list)

Характеристики

improper?(maybe_improper_list()) :: boolean()

Возвращает true, если list является несобственным списком. В противном случае возвращает false.

Примеры

iex> List.improper?([1, 2 | 3])
true

iex> List.improper?([1, 2, 3])
false

insert_at(list, index, value)

Характеристики

insert_at(list(), integer(), any()) :: list()

Возвращает список с value, вставленным по указанному index.

Обратите внимание, что index ограничен длиной списка. Отрицательные индексы указывают смещение от конца list.

Примеры

iex> List.insert_at([1, 2, 3, 4], 2, 0)
[1, 2, 0, 3, 4]

iex> List.insert_at([1, 2, 3], 10, 0)
[1, 2, 3, 0]

iex> List.insert_at([1, 2, 3], -1, 0)
[1, 2, 3, 0]

iex> List.insert_at([1, 2, 3], -10, 0)
[0, 1, 2, 3]

keydelete(list, key, position)

Характеристики

keydelete([tuple()], any(), non_neg_integer()) :: [tuple()]

Принимает list кортежей и удаляет первый кортеж, где элемент по position соответствует заданному key. Возвращает новый список.

Примеры

iex> List.keydelete([a: 1, b: 2], :a, 0)
[b: 2]

iex> List.keydelete([a: 1, b: 2], 2, 1)
[a: 1]

iex> List.keydelete([a: 1, b: 2], :c, 0)
[a: 1, b: 2]

keyfind(list, key, position, default \\ nil)

Характеристики

keyfind([tuple()], any(), non_neg_integer(), any()) :: any()

Принимает список кортежей и возвращает первый кортеж, где элемент по position в кортеже соответствует заданному key.

Если соответствующий кортеж не найден, возвращается default.

Примеры

iex> List.keyfind([a: 1, b: 2], :a, 0)
{:a, 1}

iex> List.keyfind([a: 1, b: 2], 2, 1)
{:b, 2}

iex> List.keyfind([a: 1, b: 2], :c, 0)
nil

keymember?(list, key, position)

Характеристики

keymember?([tuple()], any(), non_neg_integer()) :: boolean()

Принимает список кортежей и возвращает true, если существует кортеж, где элемент по position в кортеже соответствует заданному key.

Примеры

iex> List.keymember?([a: 1, b: 2], :a, 0)
true

iex> List.keymember?([a: 1, b: 2], 2, 1)
true

iex> List.keymember?([a: 1, b: 2], :c, 0)
false

keyreplace(list, key, position, new_tuple)

Характеристики

keyreplace([tuple()], any(), non_neg_integer(), tuple()) :: [tuple()]

Принимает список кортежей и, если идентифицированный элемент по key в position существует, заменяет его на new_tuple.

Примеры

iex> List.keyreplace([a: 1, b: 2], :a, 0, {:a, 3})
[a: 3, b: 2]

iex> List.keyreplace([a: 1, b: 2], :a, 1, {:a, 3})
[a: 1, b: 2]

keysort(list, position)

Характеристики

keysort([tuple()], non_neg_integer()) :: [tuple()]

Принимает список кортежей и сортирует элементы по position кортежей. Сортировка стабильна.

Примеры

iex> List.keysort([a: 5, b: 1, c: 3], 1)
[b: 1, c: 3, a: 5]

iex> List.keysort([a: 5, c: 1, b: 3], 0)
[a: 5, b: 3, c: 1]

keystore(list, key, position, new_tuple)

Характеристики

keystore([tuple()], any(), non_neg_integer(), tuple()) :: [tuple(), ...]

Принимает list кортежей и заменяет элемент, идентифицированный по key в position на new_tuple.

Если элемент не существует, он добавляется в конец list.

Примеры

iex> List.keystore([a: 1, b: 2], :a, 0, {:a, 3})
[a: 3, b: 2]

iex> List.keystore([a: 1, b: 2], :c, 0, {:c, 3})
[a: 1, b: 2, c: 3]

keytake(list, key, position)

Характеристики

keytake([tuple()], any(), non_neg_integer()) :: {tuple(), [tuple()]} | nil

Принимает list кортежей и возвращает первый кортеж, где элемент по position в кортеже соответствует заданному key, а также list без найденного кортежа.

Если такой кортеж не найден, возвращается nil.

Примеры

iex> List.keytake([a: 1, b: 2], :a, 0)
{{:a, 1}, [b: 2]}

iex> List.keytake([a: 1, b: 2], 2, 1)
{{:b, 2}, [a: 1]}

iex> List.keytake([a: 1, b: 2], :c, 0)
nil

last(list)

Характеристики

last([]) :: nil
last([elem, ...]) :: elem when elem: var

Возвращает последний элемент в list или nil, если list пустой.

Примеры

iex> List.last([])
nil

iex> List.last([1])
1

iex> List.last([1, 2, 3])
3

myers_difference(list1, list2)

Характеристики

myers_difference(list(), list()) :: [{:eq | :ins | :del, list()}]

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

Алгоритм описан в статье «Алгоритм разницы O(ND) и его вариации» Э. Майерса.

Сценарий редактирования — это список ключевых слов. Каждый ключ описывает «действие редактирования», которое необходимо выполнить, чтобы сделать list1 ближе к равенству с list2; ключ может быть :eq, :ins, или :del. Каждое значение — это подсписок list1 или list2, который следует вставить (если соответствующий ключ :ins), удалить (если соответствующий ключ :del ) или оставить без изменений (если соответствующий ключ :eq) в list1 для приближения к list2.

См. myers_difference/3, если требуется обработка вложенных сценариев разницы.

Примеры

iex> List.myers_difference([1, 4, 2, 3], [1, 2, 3, 4])
[eq: [1], del: [4], eq: [2, 3], ins: [4]]

myers_difference(list1, list2, diff_script)

Характеристики

myers_difference(list(), list(), (term(), term() -> script | nil)) :: script
when script: [{:eq | :ins | :del | :diff, list()}]

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

Это расширение myers_difference/2, где в случае необходимости вычисления вложенных различий можно задать функцию diff_script. Функция может вернуть список с внутренним сценарием редактирования или nil, если такого сценария нет. Возвращаемый внутренний сценарий редактирования будет под ключом :diff.

Примеры

iex> List.myers_difference(["a", "db", "c"], ["a", "bc"], &String.myers_difference/2)
[eq: ["a"], diff: [del: "d", eq: "b", ins: "c"], del: ["c"]]

pop_at(list, index, default \\ nil)

Характеристики

pop_at(list(), integer(), any()) :: {any(), list()}

Возвращает и удаляет значение по указанному index в list.

Отрицательные индексы обозначают смещение от конца list. Если index выходит за пределы, возвращается исходное list.

Примеры

iex> List.pop_at([1, 2, 3], 0)
{1, [2, 3]}
iex> List.pop_at([1, 2, 3], 5)
{nil, [1, 2, 3]}
iex> List.pop_at([1, 2, 3], 5, 10)
{10, [1, 2, 3]}
iex> List.pop_at([1, 2, 3], -1)
{3, [1, 2]}

replace_at(list, index, value)

Характеристики

replace_at(list(), integer(), any()) :: list()

Возвращает список с изменённым значением по указанному index.

Отрицательные индексы обозначают смещение от конца list. Если index выходит за пределы, возвращается исходное list.

Примеры

iex> List.replace_at([1, 2, 3], 0, 0)
[0, 2, 3]

iex> List.replace_at([1, 2, 3], 10, 0)
[1, 2, 3]

iex> List.replace_at([1, 2, 3], -1, 0)
[1, 2, 0]

iex> List.replace_at([1, 2, 3], -10, 0)
[1, 2, 3]

starts_with?(list, prefix)

Характеристики

starts_with?([...], [...]) :: boolean()
starts_with?(list(), []) :: true
starts_with?([], [...]) :: false

Возвращает true , если list начинается с данного списка prefix; в противном случае возвращает false.

Если prefix пустой список, возвращается true.

Примеры

iex> List.starts_with?([1, 2, 3], [1, 2])
true

iex> List.starts_with?([1, 2], [1, 2, 3])
false

iex> List.starts_with?([:alpha], [])
true

iex> List.starts_with?([], [:alpha])
false

to_atom(charlist)

Характеристики

to_atom(charlist()) :: atom()

Преобразует список символов в атом.

Elixir поддерживает преобразования из списков символов, содержащих любые символы Юникода.

Встраивается компилятором.

Примеры

iex> List.to_atom('Elixir')
:Elixir

iex> List.to_atom('🌢 Elixir')
:"🌢 Elixir"

to_charlist(list)

Характеристики

to_charlist(:unicode.charlist()) :: charlist()

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

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

Примеры

iex> List.to_charlist([0x00E6, 0x00DF])
'æß'

iex> List.to_charlist([0x0061, "bc"])
'abc'

iex> List.to_charlist([0x0064, "ee", ['p']])
'deep'

to_existing_atom(charlist)

Характеристики

to_existing_atom(charlist()) :: atom()

Преобразует список символов в существующий атом. Вызывает ArgumentError, если атом не существует.

Elixir поддерживает преобразования из списков символов, содержащих любые символы Юникода.

Встраивается компилятором.

Примеры

iex> _ = :my_atom
iex> List.to_existing_atom('my_atom')
:my_atom

iex> _ = :"🌢 Elixir"
iex> List.to_existing_atom('🌢 Elixir')
:"🌢 Elixir"

iex> List.to_existing_atom('this_atom_will_never_exist')
** (ArgumentError) argument error

to_float(charlist)

Характеристики

to_float(charlist()) :: float()

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

Встраивается компилятором.

Примеры

iex> List.to_float('2.2017764e+0')
2.2017764

to_integer(charlist)

Характеристики

to_integer(charlist()) :: integer()

Возвращает целое число, текстовое представление которого charlist.

Встраивается компилятором.

Примеры

iex> List.to_integer('123')
123

to_integer(charlist, base)

Характеристики

to_integer(charlist(), 2..36) :: integer()

Возвращает целое число, текстовое представление которого charlist в системе счисления base.

Встраивается компилятором.

Примеры

iex> List.to_integer('3FF', 16)
1023

to_string(list)

Характеристики

to_string(:unicode.charlist()) :: String.t()

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

Чтобы преобразовать в строку, список должен быть пустым или содержать только следующие элементы:

  • строки
  • целые числа, представляющие код символов Юникода
  • список, содержащий один из этих трёх элементов

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

Примеры

iex> List.to_string([0x00E6, 0x00DF])
"æß"

iex> List.to_string([0x0061, "bc"])
"abc"

iex> List.to_string([0x0064, "ee", ['p']])
"deep"

iex> List.to_string([])
""

to_tuple(list)

Характеристики

to_tuple(list()) :: tuple()

Преобразует список в кортеж.

Встраивается компилятором.

Примеры

iex> List.to_tuple([:share, [:elixir, 163]])
{:share, [:elixir, 163]}

update_at(list, index, fun)

Характеристики

update_at([elem], integer(), (elem -> any())) :: list() when elem: var

Возвращает список с обновлённым значением по указанному index.

Отрицательные индексы обозначают смещение от конца list. Если index выходит за пределы, возвращается исходное list.

Примеры

iex> List.update_at([1, 2, 3], 0, &(&1 + 10))
[11, 2, 3]

iex> List.update_at([1, 2, 3], 10, &(&1 + 10))
[1, 2, 3]

iex> List.update_at([1, 2, 3], -1, &(&1 + 10))
[1, 2, 13]

iex> List.update_at([1, 2, 3], -10, &(&1 + 10))
[1, 2, 3]

wrap(term)

Характеристики

wrap(term()) :: maybe_improper_list()

Оборачивает term в список, если это не список.

Если term уже является списком, возвращается список. Если term — nil, возвращается пустой список.

Примеры

iex> List.wrap("hello")
["hello"]

iex> List.wrap([1, 2, 3])
[1, 2, 3]

iex> List.wrap(nil)
[]

zip(list_of_lists)

Характеристики

zip([list()]) :: [tuple()]

Объединяет соответствующие элементы из каждого списка в list_of_lists.

Объединение завершается, как только какой-либо список завершается.

Примеры

iex> List.zip([[1, 2], [3, 4], [5, 6]])
[{1, 3, 5}, {2, 4, 6}]

iex> List.zip([[1, 2], [3], [5, 6]])
[{1, 3, 5}]

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.9.4/List.html

Spec-Zone.ru

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