Spec-Zone.ru › Elixir 1.3

Inspect.Algebra

Набор функций для создания и обработки документов алгебры.

Этот модуль реализует функциональность, описанную в «Strictly Pretty» (2000) Кристиана Линдига с небольшими дополнениями, такими как поддержка узлов String и настраиваемая функция визуализации, которая максимизирует использование горизонтального пространства.

iex> Inspect.Algebra.empty
:doc_nil

iex> "foo"
"foo"

С помощью функций в этом модуле мы можем конкатенировать различные элементы вместе и визуализировать их:

iex> doc = Inspect.Algebra.concat(Inspect.Algebra.empty, "foo")
iex> Inspect.Algebra.format(doc, 80)
["foo"]

Функции nest/2, space/2 и line/2 помогут вам собрать документ в строгую структуру. Однако алгебра документов становится интересной при использовании функций, таких как break/2, которая преобразует заданную строку в перевод строки в зависимости от того, сколько места есть для печати. Давайте склеим два документа вместе с разрывом и затем визуализируем их:

iex> doc = Inspect.Algebra.glue("a", " ", "b")
iex> Inspect.Algebra.format(doc, 80)
["a", " ", "b"]

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

iex> doc = Inspect.Algebra.glue(String.duplicate("a", 20), " ", "b")
iex> Inspect.Algebra.format(doc, 10)
["aaaaaaaaaaaaaaaaaaaa", "\n", "b"]

Наконец, этот модуль также содержит связанные с Elixir функции, немного связанные с форматированием Elixir, а именно surround/3 и surround_many/5.

Подробности реализации

Исходная реализация алгоритма на Haskell автором Уэдлера полагается на ленивое вычисление для развертывания групп документов по двум альтернативам: :flat (разрывы как пробелы) и :break (разрывы как новые строки). Реализация того же логики на строгом языке, таком как Elixir, приводит к экспоненциальному росту возможных документов, если группы документов не закодированы явно как :flat или :break. Эти группы затем сводятся к простому документу, где макет уже определен, согласно Линдигу.

Эта реализация немного изменяет семантику алгоритма Линдига, чтобы позволить элементам, принадлежащим к одной группе, печататься вместе в одной строке, даже если они не помещаются полностью в строку. Это было достигнуто путем изменения :break для обозначения возможного разрыва и :flat для принудительной плоской структуры. Затем решение о том, работает ли разрыв как новая строка, сводится к проверке наличия достаточного места до следующего разрыва, который не находится внутри группы (которая все еще плоская).

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

Резюме

Типы

t()

Функции

break()
break(s)

Сущность документа, представляющая разрыв

concat(docs)

Конкатенирует список документов

concat(x, y)

Конкатенирует две сущности документа

empty()

Возвращает сущность документа, используемую для представления пустоты

fold_doc(list, fun)

Складывает список сущностей документов в сущность документа с использованием функции, которая передается в качестве первого аргумента

format(d, w)

Функция форматирования

glue(x, y)

Вставляет разрыв между двумя документами. См. break/1 для получения дополнительной информации

glue(x, g, y)

Вставляет разрыв, переданный во втором аргументе, между двумя документами, первым и третьим аргументами

group(d)

Возвращает группу, содержащую указанный документ

line(x, y)

Вставляет обязательный перевод строки между двумя сущностями документа

nest(x, i)

Вкладывает сущность документа x позиций глубоко

space(x, y)

Вставляет обязательный одиночный пробел между двумя сущностями документа

surround(left, doc, right)

Оборачивает документ символами

surround_many(left, docs, right, opts, fun, separator \\ ",")

Картирует и склеивает коллекцию элементов

to_doc(map, opts)

Преобразует структуру Elixir в документ алгебры в соответствии с протоколом inspect

Типы

t()

t ::
  :doc_nil |
  :doc_line |
  doc_cons |
  doc_nest |
  doc_break |
  doc_group |
  binary

Функции

break()

break() :: doc_break

break(s)

break(binary) :: doc_break

Сущность документа, представляющая разрыв.

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

Примеры

Давайте склеим два документа вместе с разрывом и затем визуализируем их:

iex> doc = Inspect.Algebra.glue("a", " ", "b")
iex> Inspect.Algebra.format(doc, 80)
["a", " ", "b"]

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

iex> doc = Inspect.Algebra.glue(String.duplicate("a", 20), " ", "b")
iex> Inspect.Algebra.format(doc, 10)
["aaaaaaaaaaaaaaaaaaaa", "\n", "b"]

concat(docs)

concat([t]) :: doc_cons

Конкатенирует список документов.

concat(x, y)

concat(t, t) :: doc_cons

Конкатенирует две сущности документа.

Примеры

iex> doc = Inspect.Algebra.concat "hello", "world"
iex> Inspect.Algebra.format(doc, 80)
["hello", "world"]

empty()

empty() :: :doc_nil

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

Примеры

iex> Inspect.Algebra.empty
:doc_nil

fold_doc(list, fun)

fold_doc([t], (t, t -> t)) :: t

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

Примеры

iex> doc = ["A", "B"]
iex> doc = Inspect.Algebra.fold_doc(doc, fn(x, y) ->
...>   Inspect.Algebra.concat [x, "!", y]
...> end)
iex> Inspect.Algebra.format(doc, 80)
["A", "!", "B"]

format(d, w)

format(t, non_neg_integer | :infinity) :: iodata

Функция форматирования.

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

glue(x, y)

glue(t, t) :: doc_cons

Вставляет разрыв между двумя документами. См. break/1 для получения дополнительной информации.

glue(x, g, y)

glue(t, binary, t) :: doc_cons

Вставляет разрыв, переданный во втором аргументе, между двумя документами, первым и третьим аргументами.

group(d)

group(t) :: doc_group

Возвращает группу, содержащую указанный документ.

Примеры

iex> doc = Inspect.Algebra.group(
...>   Inspect.Algebra.concat(
...>     Inspect.Algebra.group(
...>       Inspect.Algebra.concat(
...>         "Hello,",
...>         Inspect.Algebra.concat(
...>           Inspect.Algebra.break,
...>           "A"
...>         )
...>       )
...>     ),
...>     Inspect.Algebra.concat(
...>       Inspect.Algebra.break,
...>       "B"
...>     )
...> ))
iex> Inspect.Algebra.format(doc, 80)
["Hello,", " ", "A", " ", "B"]
iex> Inspect.Algebra.format(doc, 6)
["Hello,", "\n", "A", " ", "B"]

line(x, y)

line(t, t) :: doc_cons

Вставляет обязательный перевод строки между двумя сущностями документа.

Примеры

iex> doc = Inspect.Algebra.line "Hughes", "Wadler"
iex> Inspect.Algebra.format(doc, 80)
["Hughes", "\n", "Wadler"]

nest(x, i)

nest(t, non_neg_integer) :: doc_nest

Вкладывает сущность документа x позиций глубоко.

Вкладывание будет добавлено к переводу строк.

Примеры

iex> doc = Inspect.Algebra.nest(Inspect.Algebra.glue("hello", "world"), 5)
iex> Inspect.Algebra.format(doc, 5)
["hello", "\n     ", "world"]

space(x, y)

space(t, t) :: doc_cons

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

Примеры

iex> doc = Inspect.Algebra.space "Hughes", "Wadler"
iex> Inspect.Algebra.format(doc, 80)
["Hughes", " ", "Wadler"]

surround(left, doc, right)

surround(binary, t, binary) :: t

Оборачивает документ символами.

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

Примеры

iex> doc = Inspect.Algebra.surround "[", Inspect.Algebra.glue("a", "b"), "]"
iex> Inspect.Algebra.format(doc, 3)
["[", "a", "\n ", "b", "]"]

surround_many(left, docs, right, opts, fun, separator \\ ",")

surround_many(binary, [any], binary, Inspect.Opts.t, (term, Inspect.Opts.t -> t), binary) :: t

Картирует и склеивает коллекцию элементов.

Использует заданные левую и правую стороны в качестве ограничивающих и разделитель для каждого элемента. Может быть передан лимит, который, как только будет достигнут, прекращает склеивание и выводит «…» вместо этого.

Примеры

iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]",
...>         %Inspect.Opts{limit: :infinity}, fn i, _opts -> to_string(i) end)
iex> Inspect.Algebra.format(doc, 5) |> IO.iodata_to_binary
"[1,\n 2,\n 3,\n 4,\n 5]"

iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]",
...>         %Inspect.Opts{limit: 3}, fn i, _opts -> to_string(i) end)
iex> Inspect.Algebra.format(doc, 20) |> IO.iodata_to_binary
"[1, 2, 3, ...]"

iex> doc = Inspect.Algebra.surround_many("[", Enum.to_list(1..5), "]",
...>         %Inspect.Opts{limit: 3}, fn i, _opts -> to_string(i) end, "!")
iex> Inspect.Algebra.format(doc, 20) |> IO.iodata_to_binary
"[1! 2! 3! ...]"

to_doc(map, opts)

to_doc(any, Inspect.Opts.t) :: t

Преобразует структуру Elixir в документ алгебры в соответствии с протоколом inspect.

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.3.4/Inspect.Algebra.html

Spec-Zone.ru

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