Треки
/
Elixir
Elixir
/
Салабус
/
Специфікації типів
Сп

Специфікації типів у Elixir

1 вправа

Про концепцію Специфікації типів

Elixir - мова з динамічною типізацією, тобто вона не виконує перевірок типів під час компіляції. Утім, специфікації типів можуть бути корисними, бо вони:

  • Слугують документацією.
  • Можуть використовуватися інструментами статичного аналізу, як-от Dialyzer, для пошуку можливих помилок.

Специфікацію типу можна додати до функції за допомогою атрибута модуля @spec одразу перед визначенням функції.

@spec longer_than?(String.t(), non_neg_integer()) :: boolean()
def longer_than?(string, length), do: String.length(string) > length

Типи

Вирази, дозволені у специфікації типу:

  • Базові типи, наприклад:

    • boolean()
    • integer(), non_neg_integer(), pos_integer(), float()
    • list()
    • map()
    • any()
  • Обʼєднання типів:

    • напр. integer() | list(integer())
  • Параметризовані типи:

    • напр. list(integer()) - список цілих чисел
    • напр. %{age: integer()} - мапа з цілим значенням за ключем :age
  • Віддалені типи (визначені в якомусь модулі), наприклад:

  • Літерали, наприклад:

    • %{} - порожня мапа
    • [] - порожній список (але [any()] - це непорожній список)
    • напр. :ok - літерал атома
  • Вбудовані спеціалізовані типи, наприклад:

    • char() - ціле число з діапазону 0..0x10FFFF
    • charlist() - список символів
    • keyword() - список двоелементних кортежів, де перший елемент - атом
  • Власні типи

Повний список усіх типів можна знайти в розділі «Typespecs» в офіційній документації.

Іменування аргументів

Аргументи у специфікації типу також можна назвати, що корисно, коли треба розрізнити кілька аргументів одного типу.

@spec to_hex({hue :: integer, saturation :: integer, lightness :: integer}) :: String.t()

Власні типи

Власні типи можна визначити за допомогою одного з трьох атрибутів модуля:

  • @type - визначає публічний тип
  • @typep - визначає приватний тип
  • @opaque - визначає публічний тип, структура якого приватна
@type color :: {hue :: integer, saturation :: integer, lightness :: integer}

@spec to_hex(color()) :: String.t()

String.t() проти binary() проти string()

String.t() - правильний тип для рядків Elixir, які є бінарними даними в кодуванні UTF-8. Технічно String.t() визначено як binary(), і для інструментів аналізу ці два типи еквівалентні, але String.t() краще передає намір, коли треба задокументувати функції, що працюють із рядками Elixir.

З іншого боку, string() - це інший тип. Це рядок Erlang, який в Elixir називають списком символів. Типу string() слід уникати у специфікаціях типів, а натомість використовувати charlist().

Dialyzer

Dialyzer - інструмент статичного аналізу, який може виявляти проблеми, як-от помилки типів у коді Erlang та Elixir. Найпростіший спосіб використовувати Dialyzer у проєкті Elixir - це Dialyxir.

Редагувати через GitHub Посилання відкривається в новому вікні або вкладці

Вивчити концепцію Специфікації типів