## Линейные типы Большинство типов в YQL являются неизменяемыми, то есть выражения возвращают новые значения, а не меняют существующие. Этот подход, принятый в функциональных языках программирования, позволяет проводить более агрессивные оптимизации (например, удалять общие подвыражения или кешировать результаты). Но в некоторых сценариях это может приводить к более медленному выполнению запроса, в частности при попытке изменить одно значение в списке/словаре необходимо или возвращать полную копию, или использовать персистентные структуры данных, что также имеет дополнительные накладные расходы. Линейные типы предлагают другой подход — вместо того, чтобы переиспользовать неизменяемые результаты вычисления выражения, повторное использование значения линейного типа запрещено. Оно передается как бы по эстафете от точки создания до точки поглощения, где оно преобразуется уже в обычное неизменяемое значение. Линейные типы доступны начиная с версии [2025.04](../changelog/2025.04.md). Линейные типы описываются одним параметром-типом T и бывают двух видов — статически верифицируемые `Linear` и верифицируемые во время выполнения `DynamicLinear`. Статически верифицируемые типы более эффективные, но имеют ограничения по композиции. Обычно в параметре `T` линейного типа используется тип `Resource`. В этом случае пользовательские функции (UDF) могут передавать такие данные друг другу с гарантией защиты от повторного использования в запросе, что позволяет использовать более эффективную реализацию. Линейные типы не являются сериализуемыми — их нельзя прочитать/записать в таблицы, т.е. их можно использовать только в середине выражений. Функции, принимающие или возвращающие линейные типы, делятся на 3 класса: * Если линейный тип содержится в результате, но не в аргументах - это порождающая функция; * Если линейный тип содержится и в аргументах и в результате - это трансформирующая функция; * Если линейный тип содержится в аргументах, но не в результате - это поглощающая функция. Порождающая функция обязательно принимает зависимое выражение как минимум в одном аргументе, так как можно построить из входных аргументов несколько независимых значений линейных типов. Создавать и поглощать линейные типы рекомендуется внутри функции [`Block`](../builtins/basic.md#block), позволяющей ввести анонимное зависимое выражение как аргумент `lambda`. ### Правила проверки статических линейных типов `Linear` * `Linear` типы проверяются как последняя стадия оптимизации, и, если оптимизатор устранил повторное использование выражения, то ошибки не возникает. * `Linear` тип не может быть аргументом `lambda`. * `Linear` тип не может возвращаться из `lambda`. * `Linear` тип можно использовать либо сам по себе, либо как поле в `Struct/Tuple` (без вложенности). При этом по возможности отслеживается индивидуальное использование полей `Struct/Tuple` через оператор обращения к полю (точка). При необходимости использования значений линейных типов внутри других контейнерных типов (например, в списках) следует использовать `DynamicLinear` тип. ### Правила проверки динамических линейных типов `DynamicLinear` * Функция `FromDynamicLinear` или пользовательские функции (UDF) могут извлечь значение такого типа, но не более одного раза - иначе возникнет ошибка выполнения запроса.