Spec-Zone.ru › Elixir 1.5

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/1, которая преобразует заданную строку в разрыв строки в зависимости от имеющегося пространства для печати. Давайте объединим два документа с разрывом и отобразим их:

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 Wadler полагается на ленивое вычисление для раскрытия групп документов по двум альтернативам: :flat (пробелы в качестве разрывов) и :break (новые строки в качестве разрывов). Реализация той же логики в строгом языке, таком как Elixir, приводит к экспоненциальному росту возможных документов, если группы документов не закодированы явно как :flat или :break. Эти группы затем сводятся к простому документу, где макет уже определён, согласно Lindig.

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

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

Резюме

Типы

t()

Функции

break()

Возвращает элемент документа с " " строкой в качестве разрыва

break(string)

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

color(doc, color_key, opts)

Окрашивает документ, если color_key имеет цвет в опциях

concat(docs)

Объединяет список документов, возвращая новый документ

concat(doc1, doc2)

Объединяет два элемента документа, возвращая новый документ

empty()

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

fold_doc(docs, folder_fun)

Складывает список документов в документ, используя заданную функцию сложения

format(doc, width)

Форматирует заданный документ для заданной ширины

glue(doc1, doc2)

Объединяет два документа, вставляя " " в качестве разрыва между ними

glue(doc1, break_string, doc2)

Объединяет два документа (doc1 и doc2) вместе, вставляя заданный разрыв break_string между ними

group(doc)

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

line(doc1, doc2)

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

nest(doc, level)

Вгнеждает заданный документ на заданном level уровне

space(doc1, doc2)

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

surround(left, doc, right)

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

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

Осуществляет отображение и склеивание коллекции элементов

to_doc(term, opts)

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

Типы

t()

t() ::
  :doc_nil |
  :doc_line |
  doc_cons() |
  doc_nest() |
  doc_break() |
  doc_group() |
  doc_color() |
  binary()

Функции

break()

break() :: doc_break()

Возвращает элемент документа со строкой " " в качестве разрыва.

См. break/1 для получения дополнительной информации.

break(string)

break(binary()) :: doc_break()

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

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

Примеры

Давайте создадим документ, объединяя две строки с разрывом между ними:

iex> doc = Inspect.Algebra.concat(["a", Inspect.Algebra.break("\t"), "b"])
iex> Inspect.Algebra.format(doc, 80)
["a", "\t", "b"]

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

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

color(doc, color_key, opts)

color(t(), Inspect.Opts.color_key(), Inspect.Opts.t()) :: doc_color()

Окрашивает документ, если color_key имеет цвет в опциях.

concat(docs)

concat([t()]) :: t()

Объединяет список документов, возвращая новый документ.

Примеры

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

concat(doc1, doc2)

concat(t(), t()) :: t()

Объединяет два элемента документа, возвращая новый документ.

Примеры

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(docs, folder_fun)

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

Складывает список документов в документ, используя заданную функцию сложения.

Список документов складывается «справа»; в этом отношении эта функция похожа на List.foldr/3, за исключением того, что она не ожидает начального аккумулятора и использует последний элемент docs в качестве начального аккумулятора.

Примеры

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

format(doc, width)

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

Форматирует заданный документ для заданной ширины.

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

Примеры

iex> doc = Inspect.Algebra.glue("hello", " ", "world")
iex> Inspect.Algebra.format(doc, 30) |> IO.iodata_to_binary()
"hello world"
iex> Inspect.Algebra.format(doc, 10) |> IO.iodata_to_binary()
"hello\nworld"

glue(doc1, doc2)

glue(t(), t()) :: t()

Объединяет два документа, вставляя " " в качестве разрыва между ними.

Это означает, что два документа будут разделены " " в случае, если они поместятся в одну строку. В противном случае используется разрыв строки.

Примеры

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

glue(doc1, break_string, doc2)

glue(t(), binary(), t()) :: t()

Объединяет два документа (doc1 и doc2) вместе, вставляя заданный разрыв break_string между ними.

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

Примеры

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

group(doc)

group(t()) :: doc_group()

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

Документы в группе пытаются отображаться вместе по возможности.

Примеры

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(doc1, doc2)

line(t(), t()) :: t()

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

Примеры

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

nest(doc, level)

nest(t(), non_neg_integer()) :: doc_nest()

Вгнеждает заданный документ на заданном level уровне.

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

Примеры

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

space(doc1, doc2)

space(t(), t()) :: t()

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

Примеры

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

surround(left, doc, right)

surround(t(), t(), t()) :: t()

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

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

Примеры

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(t(), [any()], t(), Inspect.Opts.t(), (term(), Inspect.Opts.t() -> t()), t()) :: t()

Отображает и склеивает коллекцию элементов.

Использует заданные left и right документы в качестве окружающих и документ-разделитель separator для разделения элементов в docs. Можно указать предел: когда этот предел достигнут, функция останавливает склеивание и выводит "..." вместо.

Примеры

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(term, 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.5.3/Inspect.Algebra.html

Spec-Zone.ru

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