Знакомлюсь с аннотациями на примере документации evolved ECS

Бороздя GitHub репозитории, наверняка, вы замечали какие-то странные комментарии к коду по типу:

---@param count? integer
---@return evolved.id ... ids
---@nodiscard
function evolved.id(count) end

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

На нескольких примеров из документации к ECS evolved мы попробуем научиться читать аннотации:

Образец 1:
---@param count? integer
---@return evolved.id ... ids
---@nodiscard
function evolved.id(count) end

Детали:

  • Каждая строка, начинающаяся с ---@ , считается отдельной аннотацией
  • Аннотации располагаются непосредственно перед объявлением функции
---@param count? integer
  • --- — это синтаксис аннотации для Lua-комментариев
  • @param — аннотация параметра функции
  • count? — имя параметра, знак ? означает необязательный параметр
  • integer — ожидаемый тип данных (целое число)
---@return evolved.id ... ids
  • @return — аннотация возвращаемого значения.
  • evolved.id — тип возвращаемого значения (пользовательский тип из библиотеки).
  • ... — означает, что возвращается переменное количество значений этого типа
  • ids — символическое имя для возвращаемых значений (для документации evolved). ids просто помогает понять, что возвращает функция.
---@nodiscard
  • Указывает, что возвращаемое значение не должно игнорироваться
Образец 2:
---@param ... evolved.id ids
---@return string... names
---@nodiscard
function evolved.name(...) end
---@param ... evolved.id ids
  • ... — функция принимает переменное количество аргументов (varargs)
  • evolved.id — тип каждого передаваемого аргумента
  • ids — описательное имя для этих аргументов. Функция принимает любое количество аргументов типа evolved.id, которые мы будем называть ids.
---@return string... names
  • string... — функция возвращает переменное количество строк
  • names — описательное имя для возвращаемых строк. Функция возвращает несколько строк, которые мы будем называть names.
---@nodiscard
  • Запрещает игнорировать возвращаемое значение.
  • Вызовет предупреждение анализатора, если результат не будет использован.
Образец 3:
---@param primary integer
---@param secondary integer
---@return evolved.id id
---@nodiscard
function evolved.pack(primary, secondary) end

Функция evolved.pack :

  1. Принимает два целых числа: primary и secondary
  2. Возвращает один объект типа evolved.id , упаковывая оба числа в него
  3. Требует использования возвращаемого значения

Параметр primary типа целое число:

---@param primary integer

  • Параметр secondary типа целое число

---@param secondary integer

  • Параметр secondary типа целое число

---@return evolved.id id

  • Функция возвращает один результат типа evolved.id (пользовательский тип).
  • id - поясняющее имя возвращаемого значения.

---@nodiscard
Возвращаемое значение нельзя игнорировать - компилятор/анализатор предупредит, если результат не используется.

Образец 4:
---@param id evolved.id
---@return integer primary
---@return integer secondary
---@nodiscard
function evolved.unpack(id) end
---@param id evolved.id
  • id — имя параметра.
  • evolved.id — тип параметра.
---@return integer primary
  • Описывает первое возвращаемое значение типа integer.
  • primary — это просто читаемое имя для возвращаемого значения, помогающее понять его назначение (например, основной компонент идентификатора).
@return integer secondary
  • Описывает второе возвращаемое значение типа integer.
  • secondary — вспомогательный или второстепенный компонент идентификатора.

В Lua функции могут возвращать несколько значений, и каждое из них можно документировать отдельно.

---@nodiscard

Это атрибут-подсказка, говорящая:

«Результат этой функции не должен игнорироваться».

Образец 5:
---@return boolean started
function evolved.defer() end
---@return boolean started
  • Описывает возвращаемое значение типа boolean.
  • startedимя или метка возвращаемого значения. Полезно для документации и читаемости.
Образец 6:
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity entity
function evolved.spawn(components) end
---@param components? table<evolved.fragment, evolved.component>

Описывает параметр функции :

  • components — имя параметра.
  • ? (вопросительный знак) означает, что параметр необязательный (может быть nil).
  • table<evolved.fragment, evolved.component> — тип параметра: это таблица (ассоциативный массив), где:
    • Ключи имеют тип evolved.fragment,
    • Значения имеют тип evolved.component.
---@return evolved.entity entity

Описывает возвращаемое значение:

  • Тип возвращаемого значения: evolved.entity — вероятно, пользовательский тип, представляющий идентификатор сущности (например, целое число, строка или объект).
  • entity — имя/метка для этого возвращаемого значения (для читаемости и подсказок в IDE).
Образец 7:
---@param entity_count integer
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity[] entity_list
---@return integer entity_count
function evolved.multi_spawn(entity_count, components) end
---@param entity_count integer

Описывает первый обязательный параметр:

  • Имя параметра: entity_count
  • Тип: integer — целое число
  • Назначение: сколько сущностей нужно создать

Пример: 5 → создать 5 сущностей

---@param components? table<evolved.fragment, evolved.component>

Описывает второй, необязательный параметр (об этом говорит ? )

  • Имя параметра: components
  • Тип: table<evolved.fragment, evolved.component> — это ассоциативная таблица (map), где:
    • Ключи — значения типа evolved.fragment (например, position, health как метки типов)
    • Значения — объекты или данные типа evolved.component (например, {x = 10, y = 20})

Эта таблица задаёт общий набор компонентов, который будет скопирован в каждую из создаваемых сущностей.

Так как параметр помечен ?, его можно опустить — тогда новые сущности будут созданы без компонентов.

---@return evolved.entity[] entity_list

Описывает первое возвращаемое значение:

  • Тип: evolved.entity[]массив (индексированная таблица) значений типа evolved.entity
  • Имя: entity_list — для ясности (это список созданных сущностей)

Пример возвращаемого значения: {entity1, entity2, entity3, ...}

Замечание: в Lua нет настоящих “массивов”, но T[] — стандартный способ обозначить список элементов типа T.

---@return integer entity_count

Описывает второе возвращаемое значение:

  • Тип: integer
  • Имя: entity_count
Образец 8:
---@param prefab evolved.entity
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity entity
function evolved.clone(prefab, components) end
---@param prefab evolved.entity
  • Описываем обязательный параметр с именем prefab, типа evolved.entity (какой-то заготовленный идентификатор сущности).
---@param components? table<evolved.fragment, evolved.component>
  • prefab — имя первого параметра.
  • Тип: evolved.entity — это, скорее всего, идентификатор существующей сущности (например, целое число или уникальный тег), которая используется как шаблон (prefab).
  • Слово prefab (от “prefabricated object”) в игровых движках и ECS-системах означает заготовленную сущность, которую можно клонировать.

Пример: у вас есть “враг-шаблон” с компонентами (позиция, здоровье, ИИ), и вы хотите создать его копию.

---@param components? table<evolved.fragment, evolved.component>
  • components — второй параметр, необязательный (об этом говорит ? — может быть nil).
  • Тип: table<evolved.fragment, evolved.component> — ассоциативная таблица, где:
    • Ключи — метки типов компонентов (evolved.fragment, например, position, health),
    • Значения — конкретные данные компонентов (evolved.component).

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

---@return evolved.entity entity
  • Функция возвращает одну сущность типа evolved.entity.
  • Имя возвращаемого значения: entity — для ясности (это новая, клонированная сущность).
Образец 9:
---@param entity_count integer
---@param prefab evolved.entity
---@param components? table<evolved.fragment, evolved.component>
---@return evolved.entity[] entity_list
---@return integer entity_count
function evolved.multi_clone(entity_count, prefab, components) end
---@param entity_count integer
  • Параметр: entity_count
  • Тип: integer — целое число
---@param prefab evolved.entity
  • Параметр: prefab
  • Тип: evolved.entity — идентификатор существующей сущности, используемой как шаблон (prefab).
---@param components? table<evolved.fragment, evolved.component>
  • Параметр: componentsнеобязательный (об этом говорит ?, может быть nil)
  • Тип: ассоциативная таблица, где:
    • Ключи: evolved.fragment — метки типов компонентов (к примеру: position, health, renderable и т.д.)
    • Значения: evolved.component — конкретные данные компонентов
---@return evolved.entity[] entity_list
  • Возвращает: массив (список) сущностей
  • Тип: evolved.entity[] — таблица, индексированная числами (1, 2, 3…), где каждый элемент — идентификатор новой сущности
  • Имя: entity_list — для читаемости и подсказок в IDE

Всем спасибо!

1 Like