Spec-Zone.ru › Elixir 1.13

Справочник по синтаксису

Синтаксис Elixir разработан для прямого преобразования в абстрактное синтаксическое дерево (AST). Это означает, что синтаксис Elixir в основном единообразен с небольшим количеством конструкций «синтаксического сахара», чтобы уменьшить шум в общих выражениях Elixir.

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

Зарезервированные слова

Ниже приведены зарезервированные слова языка Elixir. Они подробно рассматриваются в этом руководстве, но здесь суммированы для удобства:

  • true, false, nil - используются как атомы
  • when, and, or, not, in - используются как операторы
  • fn - используется для определения анонимных функций
  • do, end, catch, rescue, after, else - используются в блоках do-end

Типы данных

Числа

Целые числа (1234) и числа с плавающей точкой (123.4) в Elixir представлены как последовательность цифр, которые могут быть разделены подчеркиваниями для повышения читабельности, например, 1_000_000. Целые числа никогда не содержат точки (.) в своем представлении. Числа с плавающей точкой содержат точку и по крайней мере одну другую цифру после точки. Числа с плавающей точкой также поддерживают научную запись, например, 123.4e10 или 123.4E10.

Атомы

Незаявленные атомы начинаются с двоеточия (:), за которым сразу должна следовать буква Unicode или подчеркивание. Атом может продолжаться, используя последовательность букв, цифр, подчеркиваний и @. Атомы могут заканчиваться ! или ?. См. Синтаксис Unicode для формального описания. Действительными незаявленными атомами являются: :ok, :ISO8601, и :integer?.

Если за двоеточием следует пара двойных или одинарных кавычек, окружающих имя атома, атом считается заявленным. В отличие от незаявленного атома, этот может состоять из любого символа Unicode (а не только букв), например, :'🌢 Elixir', :"++olá++", и :"123".

Заявленные и незаявленные атомы с одинаковым именем считаются эквивалентными, поэтому :atom, :"atom", и :'atom' представляют один и тот же атом. Единственное исключение состоит в том, что компилятор выведет предупреждение, когда в атомах используются кавычки, которые не нужно заключать в кавычки.

Все операторы в Elixir также являются допустимыми атомами. Действительные примеры — :foo, :FOO, :foo_42, :foo@bar, и :++. Недействительные примеры — :@foo (@ не допускается в начале), :123 (цифры не допускаются в начале) и :(*) (не является допустимым оператором).

true, false, и nil — это зарезервированные слова, которые представляются атомами :true, :false и :nil соответственно.

Строки

Однострочные строки в Elixir записываются между двойными кавычками, например, "foo". Любая двойная кавычка внутри строки должна быть экранирована с помощью \. Строки поддерживают символы Unicode и хранятся в виде бинарных данных, закодированных в UTF-8.

Многострочные строки в Elixir записываются с тремя двойными кавычками и могут содержать неэкранированные кавычки внутри них. Результирующая строка будет заканчиваться символом новой строки. Отступ последнего """ используется для удаления отступа из внутренней строки. Например:

iex> test = """
...>     this
...>     is
...>     a
...>     test
...> """
"    this\n    is\n    a\n    test\n"
iex> test = """
...>     This
...>     Is
...>     A
...>     Test
...>     """
"This\nIs\nA\nTest\n"

Строки всегда представляются в AST как есть.

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

Списки символов в Elixir записываются в одинарных кавычках, например, 'foo'. Любая одинарная кавычка внутри строки должна быть экранирована с помощью \. Списки символов состоят из неотрицательных целых чисел, где каждое целое число представляет собой код символа Unicode.

Многострочные списки символов записываются с тремя одинарными кавычками ('''), так же, как и многострочные строки.

Списки символов всегда представляются в AST как есть.

Для более подробной информации ознакомьтесь с разделом «Списки символов» в модуле List.

Списки, кортежи и бинарные данные

Структуры данных, такие как списки, кортежи и бинарные данные, помечаются соответственно разделителями [...], {...}, и <<...>>. Каждый элемент разделяется запятой. Разрешается и завершающая запятая, как, например, в [1, 2, 3,].

Карты и списки ключевых слов

Карты используют обозначение %{...} и каждое ключевое значение задается парами, помеченными =>, например, %{"hello" => 1, 2 => "world"}.

Как списки ключевых слов (список кортежей из двух элементов, где первый элемент — атом), так и карты с атомными ключами поддерживают обозначение ключевых слов, где символ двоеточия : перемещается в конец атома. %{hello: "world"} эквивалентно %{:hello => "world"}, а [foo: :bar] эквивалентно [{:foo, :bar}]. Это обозначение является синтаксическим сахаром, который генерирует то же представление AST. Оно будет объяснено в последующих разделах.

Структуры

Структуры строятся на основе синтаксиса карт, передавая имя структуры между % и {. Например, %User{...}.

Выражения

Переменные

Переменные в Elixir должны начинаться с подчеркивания или буквы Unicode, которая не находится в верхнем или прописном регистре. Переменная может продолжаться, используя последовательность букв Unicode, цифр и подчеркиваний. Переменные могут заканчиваться ? или !. См. Синтаксис Unicode для формального описания.

Рекомендации по именованию в Elixir рекомендуют использовать переменные в формате snake_case.

Неквалифицированные вызовы (локальные вызовы)

Неквалифицированные вызовы, такие как add(1, 2), должны начинаться с подчеркивания или буквы Unicode, которая не находится в верхнем или прописном регистре. Вызов может продолжаться, используя последовательность букв Unicode, цифр и подчеркиваний. Вызовы могут заканчиваться ? или !. См. Синтаксис Unicode для формального описания.

Скобки для неквалифицированных вызовов необязательны, за исключением вызовов нулевой арности, которые в противном случае были бы неоднозначны с переменными. Если скобки используются, они должны следовать за именем функции без пробелов. Например, add (1, 2) — синтаксическая ошибка, так как (1, 2) обрабатывается как недопустимый блок, который пытаются передать в качестве единственного аргумента функции add.

Рекомендации по именованию в Elixir рекомендуют использовать вызовы в формате snake_case.

Операторы

Как и многие языки программирования, Elixir также поддерживает операторы как неквалифицированные вызовы с их правилами приоритета и ассоциативности. Конструкции, такие как =, when, & и @ просто обрабатываются как операторы. См. страницу «Операторы» для получения полной справки.

Квалифицированные вызовы (удаленные вызовы)

Квалифицированные вызовы, такие как Math.add(1, 2), должны начинаться с подчеркивания или буквы Unicode, которая не находится в верхнем или прописном регистре. Вызов может продолжаться, используя последовательность букв Unicode, цифр и подчеркиваний. Вызовы могут заканчиваться ? или !. См. Синтаксис Unicode для формального описания.

Рекомендации по именованию в Elixir рекомендуют использовать вызовы в формате snake_case.

Для квалифицированных вызовов Elixir также позволяет записывать имя функции между двойными или одинарными кавычками, что позволяет использовать вызовы, такие как Math."++add++"(1, 2). Операторы могут использоваться в качестве квалифицированных вызовов без кавычек, например, Kernel.+(1, 2).

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

Псевдонимы

Псевдонимы — это конструкции, которые расширяются до атомов во время компиляции. Псевдоним String расширяется до атома :"Elixir.String". Псевдонимы должны начинаться с прописной латинской буквы, за которой может следовать любая латинская буква, цифра или подчеркивание. Символы, отличные от ASCII, в псевдонимах не поддерживаются.

Рекомендации по именованию в Elixir рекомендуют использовать псевдонимы в формате CamelCase.

Блоки

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

Стрелка слева направо

Стрелка слева направо (->) используется для установления связи между левой и правой частями, обычно называемыми клаузами. В левой части может быть ноль, один или несколько аргументов; правая часть — это ноль, один или несколько выражений, разделенных новой строкой. -> может появляться один или несколько раз между одним из следующих разделителей: do-end, fn-end или (-). Когда используется ->, между этими разделителями разрешаются только другие клаузы. Смешивание клауз и обычных выражений является недопустимым синтаксисом.

Он наблюдается в конструкциях case и cond между do и end:

case 1 do
  2 -> 3
  4 -> 5
end

cond do
  true -> false
end

Наблюдается в типах между ( и ):

(integer(), boolean() -> integer())

Также используется между fn и end для построения анонимных функций:

fn
  x, y -> x + y
end

Сигилы

Сигилы начинаются с ~ и следуют за буквой и одной из следующих пар:

  • ( и )
  • { и }
  • [ и ]
  • < и >
  • " и "
  • ' и '
  • | и |
  • / и /

После закрытия пары можно указать ноль или более символов ASCII в качестве модификатора. Сигилы выражаются как вызовы без квалификатора, префикс sigil_, где первый аргумент — содержимое сигила как строка, а второй — список целых чисел в качестве модификаторов:

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

~s/f#{"o"}o/
~S/f#{"o"}o/

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

АБСТРАКТНОЕ СИНАКСИЧЕСКОЕ ДЕРЕВО Elixir

Синтаксис Elixir был разработан для простого преобразования в абстрактное синтаксическое дерево (AST). AST Elixir — это обычная структура данных Elixir, состоящая из следующих элементов:

  • атомы — такие как :foo
  • целые числа — такие как 42
  • вещественные числа — такие как 13.1
  • строки — такие как "hello"
  • списки — такие как [1, 2, 3]
  • кортежи из двух элементов — такие как {"hello", :world}
  • кортежи из трёх элементов, представляющие вызовы или переменные, как объяснено далее

Основным элементом AST Elixir является вызов, например:

sum(1, 2, 3)

который представлен кортежем из трёх элементов:

{:sum, meta, [1, 2, 3]}

первый элемент — это атом (или другой кортеж), второй элемент — список кортежей из двух элементов со метаданными (такими как номера строк), а третий — список аргументов.

Мы можем получить AST для любого выражения Elixir, вызвав quote:

quote do
  sum()
end
#=> {:sum, [], []}

Переменные также представляются кортежем из трёх элементов и сочетанием списков и атомов, например:

quote do
  sum
end
#=> {:sum, [], Elixir}

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

В рамках этого раздела мы рассмотрим много синтаксических конструкций Elixir вместе с их представлениями AST.

Операторы

Операторы обрабатываются как вызовы без квалификатора:

quote do
  1 + 2
end
#=> {:+, [], [1, 2]}

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

quote do
  foo.bar(1, 2, 3)
end
#=> {{:., [], [{:foo, [], Elixir}, :bar]}, [], [1, 2, 3]}

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

quote do
  foo.(1, 2, 3)
end
#=> {{:., [], [{:foo, [], Elixir}]}, [], [1, 2, 3]}

Псевдонимы

Псевдонимы представляются вызовом __aliases__ с каждым сегментом, разделённым точкой, в качестве аргумента:

quote do
  Foo.Bar.Baz
end
#=> {:__aliases__, [], [:Foo, :Bar, :Baz]}

quote do
  __MODULE__.Bar.Baz
end
#=> {:__aliases__, [], [{:__MODULE__, [], Elixir}, :Bar, :Baz]}

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

Структуры данных

Помните, что списки — это литералы, поэтому они представлены собой в AST:

quote do
  [1, 2, 3]
end
#=> [1, 2, 3]

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

quote do
  {1, 2}
end
#=> {1, 2}

quote do
  {1, 2, 3}
end
#=> {:{}, [], [1, 2, 3]}

Бинарные данные имеют представление, аналогичное кортежам, за исключением того, что они помечены :<<>> вместо :{}:

quote do
  <<1, 2, 3>>
end
#=> {:<<>>, [], [1, 2, 3]}

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

quote do
  %{1 => 2, 3 => 4}
end
#=> {:%{}, [], [{1, 2}, {3, 4}]}

Блоки

Блоки представлены вызовом __block__ с каждой строкой в качестве отдельного аргумента:

quote do
  1
  2
  3
end
#=> {:__block__, [], [1, 2, 3]}

quote do 1; 2; 3; end
#=> {:__block__, [], [1, 2, 3]}

Стрелка слева направо

Стрелка слева направо (->) представлена аналогично операторам, за исключением того, что они всегда являются частью списка, его левая часть представляет список аргументов, а правая — выражение.

Например, в case и cond:

quote do
  case 1 do
    2 -> 3
    4 -> 5
  end
end
#=> {:case, [], [1, [do: [{:->, [], [[2], 3]}, {:->, [], [[4], 5]}]]]}

quote do
  cond do
    true -> false
  end
end
#=> {:cond, [], [[do: [{:->, [], [[true], false]}]]]}

Между ( и ):

quote do
  (1, 2 -> 3
   4, 5 -> 6)
end
#=> [{:->, [], [[1, 2], 3]}, {:->, [], [[4, 5], 6]}]

Между fn и end:

quote do
  fn
    1, 2 -> 3
    4, 5 -> 6
  end
end
#=> {:fn, [], [{:->, [], [[1, 2], 3]}, {:->, [], [[4, 5], 6]}]}

Квалифицированные кортежи

Квалифицированные кортежи (foo.{bar, baz}) представляются вызовом {:., [], [expr, :{}]}, где expr представляет левую часть точки, а аргументы — элементы внутри фигурных скобок. Это используется в Elixir для предоставления нескольких псевдонимов:

quote do
  Foo.{Bar, Baz}
end
#=> {{:., [], [{:__aliases__, [], [:Foo]}, :{}]}, [], [{:__aliases__, [], [:Bar]}, {:__aliases__, [], [:Baz]}]}

Синтаксический сахар

Все вышеперечисленные конструкции являются частью синтаксиса Elixir и имеют собственное представление в рамках AST Elixir. В этом разделе обсуждаются оставшиеся конструкции, которые «десахариваются» до одной из вышерассмотренных конструкций. Другими словами, конструкции ниже могут быть представлены в Elixir-коде более чем одним способом и сохранять эквивалентность AST.

Целые числа в других системах счисления и кодовые точки Unicode

Elixir позволяет целым числам содержать _ для разделения цифр и предоставляет удобства для представления целых чисел в других системах счисления:

1_000_000
#=> 1000000

0xABCD
#=> 43981 (Hexadecimal base)

0o01234567
#=> 342391 (Octal base)

0b10101010
#=> 170 (Binary base)

?é
#=> 233 (Unicode code point)

Эти конструкции существуют только на уровне синтаксиса. Все примеры выше представлены в качестве соответствующих целых чисел в AST.

Синтаксис доступа

Синтаксис доступа представлен вызовом Access.get/2:

quote do
  opts[arg]
end
#=> {{:., [], [Access, :get]}, [], [{:opts, [], Elixir}, {:arg, [], Elixir}]}

Необязательные скобки

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

quote do
  sum 1, 2, 3
end
#=> {:sum, [], [1, 2, 3]}

Вышеприведённое обрабатывается парсером так же, как sum(1, 2, 3). Вы можете убрать скобки из всех вызовов с по крайней мере одним аргументом.

Вы также можете опустить скобки при вызовах с квалификаторами, таких как Foo.bar 1, 2, 3. Скобки необходимы при вызове анонимных функций, таких как f.(1, 2, 3).

На практике разработчики предпочитают добавлять скобки к большинству вызовов. Они опускаются в основном в управляющих конструкциях Elixir, таких как defmodule, if, case, и т. д., и в определённых DSL.

Ключевые слова

Ключевые слова в Elixir — это список кортежей из двух элементов, где первый элемент — атом. Используя базовые конструкции, они были бы представлены как:

[{:foo, 1}, {:bar, 2}]

Однако Elixir предоставляет синтаксический сахар, где вышеуказанные ключевые слова могут быть записаны следующим образом:

[foo: 1, bar: 2]

Атомы с иностранными символами, такие как пробелы, должны быть заключены в кавычки. Это правило применяется и к ключевым словам:

[{:"foo bar", 1}, {:"bar baz", 2}] == ["foo bar": 1, "bar baz": 2]

Помните, что, поскольку списки и кортежи из двух элементов являются литералами, по определению ключевые слова также являются литералами (на самом деле, единственная причина, по которой кортежи из двух элементов являются литералами, заключается в том, чтобы поддерживать ключевые слова как литералы).

Ключевые слова как последние аргументы

Elixir также поддерживает синтаксис, где если последний аргумент вызова — список ключевых слов, то квадратные скобки можно опустить. Это означает, что следующее:

if(condition, do: this, else: that)

эквивалентно

if(condition, [do: this, else: that])

что, в свою очередь, эквивалентно

if(condition, [{:do, this}, {:else, that}])

do-end блоки

Последним синтаксическим удобством являются блоки do-end. Блоки do-end эквивалентны ключевым словам в качестве последнего аргумента вызова функции, где содержимое блока заключено в скобки. Например:

if true do
  this
else
  that
end

эквивалентно:

if(true, do: (this), else: (that))

что мы рассмотрели в предыдущем разделе.

Скобки важны для поддержки нескольких выражений. Это:

if true do
  this
  that
end

эквивалентно:

if(true, do: (
  this
  that
))

В блоках do-end вы можете использовать другие ключевые слова, такие как else , используемые в if выше. Поддерживаемые ключевые слова между do-end статичны и следующие:

  • after
  • catch
  • else
  • rescue

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

Резюме

Этот документ предоставляет справочник по синтаксису Elixir, рассматривая его конструкции и их эквиваленты AST.

Мы также рассмотрели несколько синтаксических удобств, предоставляемых Elixir. Эти удобства позволяют нам написать

defmodule Math do
  def add(a, b) do
    a + b
  end
end

вместо

defmodule(Math, [
  {:do, def(add(a, b), [{:do, a + b}])}
])

Сопоставление между кодом и данными (основным AST) позволяет Elixir реализовывать defmodule, def, if, и другие функции в самом Elixir. Elixir делает доступными для разработчиков, желающих расширить язык до новых областей, конструкции, доступные для создания языка.

← Предыдущая страница Шаблоны и проверки
Следующая страница → Типовые спецификации

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.13.4/syntax-reference.html

Spec-Zone.ru

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