Источник Сигилы
Elixir предоставляет строки в двойных кавычках, а также концепцию списков символов, которые определяются с помощью сигила ~c"hello world" синтаксиса. В этой главе мы узнаем больше о сигилах и о том, как определить свои собственные.
Одна из целей Elixir — расширяемость: разработчики должны иметь возможность расширять язык для любого конкретного домена. Сигилы обеспечивают основу для расширения языка с помощью пользовательских текстовых представлений. Сигилы начинаются с тильды (~) символа, за которым следует либо одна строчная буква, либо одна или несколько заглавных букв, а затем разделитель. Необязательные модификаторы добавляются после последнего разделителя.
Регулярные выражения
Наиболее распространённым сигилом в Elixir является ~r, который используется для создания регулярных выражений:
# A regular expression that matches strings which contain "foo" or "bar": iex> regex = ~r/foo|bar/ ~r/foo|bar/ iex> "foo" =~ regex true iex> "bat" =~ regex false
Elixir предоставляет совместимые с Perl регулярные выражения (regex), реализованные библиотекой PCRE. Регулярные выражения также поддерживают модификаторы. Например, модификатор i делает регулярное выражение регистронезависимым:
iex> "HELLO" =~ ~r/hello/ false iex> "HELLO" =~ ~r/hello/i true
Посмотрите модуль Regex для получения дополнительной информации об остальных модификаторах и поддерживаемых операциях с регулярными выражениями.
До сих пор во всех примерах использовался / для разграничения регулярного выражения. Однако сигилы поддерживают 8 различных разделителей:
~r/hello/
~r|hello|
~r"hello"
~r'hello'
~r(hello)
~r[hello]
~r{hello}
~r<hello>
Причина поддержки различных разделителей заключается в предоставлении способа записи литералов без экранированных разделителей. Например, регулярное выражение со слешами, как ~r(^https?://), читается, возможно, лучше, чем ~r/^https?:\/\//. Аналогично, если регулярное выражение содержит слеши и группы захвата (которые используют ()), вы можете выбрать двойные кавычки вместо скобок.
Сигилы для строк, списков символов и списков слов
Помимо регулярных выражений, в Elixir поставляется ещё три сигила.
Строки
Сигил ~s используется для генерации строк, как и двойные кавычки. Сигил ~s полезен, когда строка содержит двойные кавычки:
iex> ~s(this is a string with "double" quotes, not 'single' ones) "this is a string with \"double\" quotes, not 'single' ones"
Списки символов
Сигил ~c — стандартный способ представления списков символов.
iex> [?c, ?a, ?t] ~c"cat" iex> ~c(this is a char list containing "double quotes") ~c"this is a char list containing \"double quotes\""
Списки слов
Сигил ~w используется для генерации списков слов (слова — это просто обычные строки). Внутри сигила ~w слова разделяются пробелами.
iex> ~w(foo bar bat) ["foo", "bar", "bat"]
Сигил ~w также принимает модификаторы c, s и a (соответственно для списков символов, строк и атомов), которые задают тип данных элементов результирующего списка:
iex> ~w(foo bar bat)a [:foo, :bar, :bat]
Интерполяция и экранирование в сигилах строк
Elixir поддерживает некоторые варианты сигилов для обработки экранирования символов и интерполяции. В частности, сигилы с заглавными буквами не выполняют интерполяцию и экранирование. Например, хотя ~s и ~S вернут строки, первый допускает коды экранирования и интерполяцию, а второй — нет:
iex> ~s(String with escape codes \x26 #{"inter" <> "polation"})
"String with escape codes & interpolation"
iex> ~S(String without escape codes \x26 without #{interpolation})
"String without escape codes \\x26 without \#{interpolation}"
Следующие коды экранирования могут использоваться в строках и списках символов:
-
\\— одиночный обратный слэш -
\a— звонок/сигнал -
\b— возврат на одну позицию назад -
\d— удаление -
\e— экранирование -
\f— подача формы -
\n— перевод строки -
\r— возврат каретки -
\s— пробел -
\t— табуляция -
\v— вертикальная табуляция -
\0— нулевой байт -
\xDD— представляет один байт в шестнадцатеричном формате (например,\x13) -
\uDDDDи\u{D...}— представляют код Юникода в шестнадцатеричном формате (например,\u{1F600})
В дополнение к этому, двойная кавычка внутри строки в двойных кавычках должна быть экранирована как \", и, аналогично, одиночная кавычка внутри списка символов в одинарных кавычках должна быть экранирована как \'. Тем не менее, лучше стиль изменить разделители, как показано выше, чем экранировать их.
Сигилы также поддерживают heredocs, то есть три двойные или одинарные кавычки в качестве разделителей:
iex> ~s""" ...> this is ...> a heredoc string ...> """
Наиболее распространённым случаем использования сигилов heredocs является написание документации. Например, запись символов экранирования в документации вскоре станет подверженной ошибкам из-за необходимости двойного экранирования некоторых символов:
@doc """
Converts double-quotes to single-quotes.
## Examples
iex> convert("\\\"foo\\\"")
"'foo'"
"""
def convert(...)
С помощью ~S эта проблема может быть полностью устранена:
@doc ~S"""
Converts double-quotes to single-quotes.
## Examples
iex> convert("\"foo\"")
"'foo'"
"""
def convert(...)
Сигилы для дат и времени
Elixir предлагает несколько сигилов для работы с различными форматами дат и времени.
Дата
Структура %Date{} содержит поля year, month, day, и calendar. Вы можете создать её с помощью сигила ~D:
iex> d = ~D[2019-10-31] ~D[2019-10-31] iex> d.day 31
Время
Структура %Time{} содержит поля hour, minute, second, microsecond, и calendar. Вы можете создать её с помощью сигила ~T:
iex> t = ~T[23:00:07.0] ~T[23:00:07.0] iex> t.second 7
NaiveDateTime
Структура %NaiveDateTime{} содержит поля из Date и Time. Вы можете создать её с помощью сигила ~N:
iex> ndt = ~N[2019-10-31 23:00:07] ~N[2019-10-31 23:00:07]
Почему она называется наивной? Потому что она не содержит информацию о часовом поясе. Следовательно, заданная дата и время может вообще не существовать или существовать дважды в определённых часовых поясах — например, при переходе на летнее/зимнее время.
UTC DateTime
Структура %DateTime{} содержит те же поля, что и NaiveDateTime, с добавлением полей для отслеживания часовых поясов. Сигил ~U позволяет разработчикам создавать DateTime в часовом поясе UTC:
iex> dt = ~U[2019-10-31 19:59:03Z]
~U[2019-10-31 19:59:03Z]
iex> %DateTime{minute: minute, time_zone: time_zone} = dt
~U[2019-10-31 19:59:03Z]
iex> minute
59
iex> time_zone
"Etc/UTC"
Пользовательские сигилы
Как подразумевалось в начале этой главы, сигилы в Elixir расширяемы. На самом деле, использование сигила ~r/foo/i эквивалентно вызову sigil_r с бинарным и списком символов в качестве аргументов:
iex> sigil_r(<<"foo">>, [?i]) ~r"foo"i
Мы можем получить доступ к документации для сигила ~r через sigil_r:
iex> h sigil_r ...
Мы также можем предоставить свои собственные сигилы, реализовав функции, которые следуют шаблону sigil_{character}. Например, давайте реализуем сигил ~i, который возвращает целое число (с необязательным модификатором n для задания отрицательного значения):
iex> defmodule MySigils do ...> def sigil_i(string, []), do: String.to_integer(string) ...> def sigil_i(string, [?n]), do: -String.to_integer(string) ...> end iex> import MySigils iex> ~i(13) 13 iex> ~i(42)n -42
Пользовательские сигилы могут быть одной строчной буквой или заглавной буквой, за которой следуют другие заглавные буквы и цифры.
Сигилы также могут использоваться для выполнения работы на этапе компиляции с помощью макросов. Например, регулярные выражения в Elixir компилируются в эффективное представление во время компиляции исходного кода, поэтому этот шаг пропускается во время выполнения. Если вас интересует эта тема, вы можете узнать больше о макросах и посмотреть, как реализованы сигилы в модуле Kernel (где определены функции sigil_*).
© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.17.2/sigils.html