Spec-Zone.ru › Elixir 1.17

Source Правила именования

Этот документ содержит справочную информацию о правилах именования в Elixir, от регистра символов до знаков препинания.

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

Регистр символов

Разработчики Elixir должны использовать snake_case при определении переменных, имён функций, атрибутов модулей и т. п.:

some_map = %{this_is_a_key: "and a value"}
is_map(some_map)

Исключением являются псевдонимы, часто используемые в качестве имён модулей, которые должны быть прописными и написаны в CamelCase, например OptionParser. В псевдонимах заглавные буквы сохраняются в аббревиатурах, например, ExUnit.CaptureIO или Mix.SCM.

Атомы могут быть написаны либо в :snake_case , либо в :CamelCase, хотя по соглашению в Elixir используется версия с нижним регистром и знаками подчеркивания.

Как правило, имена файлов следуют snake_case соглашению о именовании модуля, который они определяют. Например, MyApp должен быть определён внутри файла my_app.ex. Однако это всего лишь соглашение. В конечном счёте, любое имя файла может быть использовано, так как они никак не влияют на скомпилированный код.

Знак подчеркивания (_foo)

Elixir использует знаки подчеркивания в разных ситуациях.

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

iex> {:ok, _contents} = File.read("README.md")

Имена функций также могут начинаться со знака подчеркивания. Такие функции никогда не импортируются по умолчанию:

iex> defmodule Example do
...>   def _wont_be_imported do
...>     :oops
...>   end
...> end

iex> import Example
iex> _wont_be_imported()
** (CompileError) iex:1: undefined function _wont_be_imported/0

Благодаря этому свойству Elixir использует функции, начинающиеся со знака подчеркивания, для добавления метаданных времени компиляции к модулям. Такие функции чаще всего имеют формат __foo__. Например, каждый модуль в Elixir имеет функцию __info__/1:

iex> String.__info__(:functions)
[at: 2, capitalize: 1, chunk: 2, ...]

Elixir также включает пять специальных форм, которые следуют формату с двумя знаками подчеркивания: __CALLER__/0, __DIR__/0, __ENV__/0и __MODULE__/0 извлекают информацию о текущей среде во время компиляции, а __STACKTRACE__/0 извлекает стек вызовов для текущей ошибки.

Заключительный восклицательный знак (foo!)

Заключительный восклицательный знак указывает на функцию или макрос, где случаи ошибок вызывают исключение.

Многие функции представлены парами, например, File.read/1 и File.read!/1. File.read/1 вернёт кортеж успеха или неудачи, в то время как File.read!/1 вернёт простое значение, иначе вызовет исключение:

iex> File.read("file.txt")
{:ok, "file contents"}
iex> File.read("no_such_file.txt")
{:error, :enoent}

iex> File.read!("file.txt")
"file contents"
iex> File.read!("no_such_file.txt")
** (File.Error) could not read file no_such_file.txt: no such file or directory

Версия без ! предпочтительнее, когда вы хотите обрабатывать различные результаты с помощью сопоставления с образцом:

case File.read(file) do
  {:ok, body} -> # do something with the `body`
  {:error, reason} -> # handle the error caused by `reason`
end

Однако, если вы ожидаете, что результат всегда будет успешным (например, если вы ожидаете, что файл всегда существует), вариант с восклицательным знаком может быть удобнее и выведет более полезное сообщение об ошибке (чем неудачное сопоставление с образцом) в случае ошибки.

При размышлении о случаях ошибок для функций мы рассматриваем только ошибки, которые происходят в их области, например, неудача при открытии файла. Ошибки, возникающие из-за неверных типов аргументов, например, всегда должны вызывать исключение, независимо от того, имеет ли функция восклицательный знак или нет. Исключением часто является ArgumentError или подробное FunctionClauseError:

iex(1)> File.read(123)
** (FunctionClauseError) no function clause matching in IO.chardata_to_string/1

    The following arguments were given to IO.chardata_to_string/1:

        # 1
        123

    Attempted function clauses (showing 2 out of 2):

        def chardata_to_string(string) when is_binary(string)
        def chardata_to_string(list) when is_list(list)

Дополнительные примеры парных функций: Base.decode16/2 и Base.decode16!/2, File.cwd/0 и File.cwd!/0.

Также существуют некоторые непарные функции без варианта без восклицательного знака. Восклицательный знак по-прежнему означает, что он вызовет исключение при неудаче. Пример: Protocol.assert_protocol!/1.

В коде макросов восклицательный знак в alias!/1 и var!/2 означает, что гигиена макросов отключается.

Заключительный вопросительный знак (foo?)

Функции, возвращающие булево значение, имеют имя с заключительным вопросительным знаком.

Примеры: Keyword.keyword?/1, Mix.debug?/0, String.contains?/2

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

Префикс is_ (is_foo)

Проверки типов и другие булевы проверки, допустимые в условиях, имеют имя с префиксом is_.

Примеры: Integer.is_even/1, is_list/1

Эти функции и макросы следуют соглашению Erlang с префиксом is_, а не с заключительным вопросительным знаком, именно для того, чтобы указать, что они допустимы в условиях.

Обратите внимание, что проверки типов, которые не допустимы в условиях, не следуют этому соглашению. Например: Keyword.keyword?/1.

Специальные имена

Некоторые имена имеют специальное значение в Elixir. Мы подробно рассмотрим эти случаи ниже.

длина и размер

Когда вы видите size в имени функции, это означает, что операция выполняется за константное время (также записывается как «O(1) время»), потому что размер хранится вместе со структурой данных.

Примеры: map_size/1, tuple_size/1

Когда вы видите length, операция выполняется за линейное время («O(n) время»), потому что вся структура данных должна быть пройдена.

Примеры: length/1, String.length/1

Другими словами, функции, использующие слово «размер» в своём имени, будут выполняться за одинаковое время, независимо от того, мала или велика структура данных. Напротив, функции, имеющие «длину» в своём имени, будут выполняться дольше по мере увеличения размера структуры данных.

получить, извлечь, извлечь!

Когда вы видите функции get, fetch, и fetch! для структур данных ключ-значение, вы можете ожидать следующего поведения:

  • get возвращает значение по умолчанию (которое по умолчанию равно nil), если ключ отсутствует, или возвращает запрошенное значение.
  • fetch возвращает :error если ключ отсутствует, или возвращает {:ok, value} если он есть.
  • fetch! вызывает исключение, если ключ отсутствует, или возвращает запрошенное значение.

Примеры: Map.get/2, Map.fetch/2, Map.fetch!/2, Keyword.get/2, Keyword.fetch/2, Keyword.fetch!/2

сравнить

Функция compare/2 должна возвращать :lt если первый термин меньше второго, :eq если два термина сравниваются как эквивалентные, или :gt если первый термин больше второго.

Примеры: DateTime.compare/2

Обратите внимание, что это конкретное соглашение важно из-за ожиданий Enum.sort/2

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

Скачать версию ePub

Разработано с помощью ExDoc (v0.34.1) для программного языка Elixir

© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.17.2/naming-conventions.html

Spec-Zone.ru

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