Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds sigils translation, refs #6 #11

Merged
merged 2 commits into from
Jul 29, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions sigils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
---
title: Сигилы
---

# Сигилы

Мы уже знаем, что в Эликсирe есть строки с двойными кавычками и списки символов с одинарными кавычками. Однако, есть и другие структуры, у которых есть текстовое представление. Например, атомы, которые в основном создаются как `:atom`.

Одна из целей Эликсира - быть расширяемым. Разработчики должны иметь возможность расширить язык таким образом, чтобы решить любую задачу. Компьютерные науки стали слишком широкой областью, чтобы ядро любого языка смогло вместить в себя все решения всех возможных проблем. Однако, если сделать язык расширяемым, то разработчики, компании и сообщества сами смогут добавить в него все необходимое.

В текущей главе, мы рассмотрим сигилы - один из встроенных в язык механизмов для работы с текстовыми представлениями. Сигилы начинаются с символа тильда (`~`), после которого идет буква (которая идентифицирует сигил) и разделитель. Опционально, после разделителя могут быть добавлены еще и модификаторы.

## Регулярные выражения

Самый часто-используемый сигил в Эликсире - сигил [регулярных выражений](https://en.wikipedia.org/wiki/Regular_Expressions): `~r`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

часто используемый раздельно


```elixir
# Регулярное выражение, которое находит в строки "foo" или "bar":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

в строкЕ

iex> regex = ~r/foo|bar/
~r/foo|bar/
iex> "foo" =~ regex
true
iex> "bat" =~ regex
false
```

Эликсир предоставляет совместимый с Перл синтаксис регулярных выражений, который реализован в библиотеке [PCRE](http://www.pcre.org/). Регулярные выражения поддерживают модификаторы. Например, модификатор `i` делает регулярное выражение нечувствительным к регистру:

```elixir
iex> "HELLO" =~ ~r/hello/
false
iex> "HELLO" =~ ~r/hello/i
true
```

В [модуле Regex](https://hexdocs.pm/elixir/Regex.html) доступно больше информации о других модификаторах и операциях с регулярными выражениями.

Пока что во всех примерах мы использовали `/` для разделения сигилов. Однако, сигилы поддерживают 8 разных типов разделителей:

```elixir
~r/hello/
~r|hello|
~r"hello"
~r'hello'
~r(hello)
~r[hello]
~r{hello}
~r<hello>
```

Причина, по которой сигилы поддерживают разные типы разделителей, заключается в возможности писать код без экранирования. Регулярное выражение с прямыми слешами записанное в виде `~r(^https?://)` читается гораздо проще, чем такое же выражение в другой форме записи `~r/^https?:\/\//`. Аналогично, если в регулярном выражении есть прямые слеши и группы (которые используют `()`), то можно использовать двойные кавычки вместо слешей.

## Строки, списки символов и сигил списка слов

Кроме регулярных выражений в языке Эликсир есть три других сигила.

### Строки

Сигил `~s` используется для создания строк, также как и двойные кавычки. Сигил `~s` полезен, когда в самой строке есть двойные кавычки:

```elixir
iex> ~s(this is a string with "double" quotes, not 'single' ones)
"this is a string with \"double\" quotes, not 'single' ones"
```

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

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

```elixir
iex> ~c(this is a char list containing 'single quotes')
'this is a char list containing \'single quotes\''
```

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

Сигил `~w` используется для создания списка слов (сами слова - обычные строки). Внутри сигила `~w` слова разделены пробелами:

```elixir
iex> ~w(foo bar bat)
["foo", "bar", "bat"]
```

Сигил `~w` поддерживает модификаторы `c`, `s` и `a` (списки символов, строки и атомы соответственно) для указания типа данных членов итогового списка:

```elixir
iex> ~w(foo bar bat)a
[:foo, :bar, :bat]
```

Кроме сигилов в нижнем регистре, Эликсир также поддерживает сигилы в верхнем регистре, чтобы работать с экранированием и интерполяцией. Оба сигила `~s` и `~S` вернут строку, с той разницей, что сигилы в верхнем регистре не поддерживают экранирование и интерполяцию:

```elixir
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}`)

В добавок, двойная кавычка внутри двойной кавычки должна быть экранирована как `\"`, аналогично и одинарная кавычка внутри одинарной кавычки `\'`. Тем не менее, лучше изменить разделители, чем использовать экранирование.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вдобавок слитно


Сигилы также поддерживают heredocs, в качестве разделителей используются три двойных или одинарных кавычки:

```elixir
iex> ~s"""
...> this is
...> a heredoc string
...> """
```

Чаще всего сигилы heredoc используют для написания документации. Например, если в документации встречается какой-то символ экранирования, то в документации могут появиться ошибки, потому что придется экранировать его дважды:

```elixir
@doc """
Converts double-quotes to single-quotes.

## Examples

iex> convert("\\\"foo\\\"")
"'foo'"

"""
def convert(...)
```

Но если использовать сигил `~S`, то такой проблемы можно полностью избежать:

```elixir
@doc ~S"""
Converts double-quotes to single-quotes.

## Examples

iex> convert("\"foo\"")
"'foo'"

"""
def convert(...)
```

## Собственные сигилы

Как уже было сказано в самом начале, сигилы - расширяемы. На самом деле использование сигила `~r/foo/i` равнозначно вызову `sigil_r` с двоичными данными и списком символов в качестве аргументов:

```elixir
iex> sigil_r(<<"foo">>, 'i')
~r"foo"i
```

Мы можем обратиться к документации сигила `~r` через `sigil_r`:

```elixir
iex> h sigil_r
...
```

Можно создавать собственные сигилы: нужно создать функцию, которая бы следовала формату `sigil_{имя_индентификатора}`. К примеру, давайте создадим сигил `~i`, который возвращает целое число (с опциональным модификатором `n`, чтобы сделать число отрицательным):

```elixir
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
```

Сигилы могут быть использованы для выполнения работы на шаге компиляции. К примеру, регулярные выражения в Эликсире компилируются в производительные структуры, чтобы работать быстрее на шаге выполнения. Если вам интересен данный вопрос, то советуем изучить, как работают макросы, и посмотреть как реализованы сигилы в модуле `Kernel` (где реализованы все `sigil_*` функции).