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