Работа с текстовым представлением типов данных
Введение
Так как YQL является строго типизированным языком, во многих аспектах работы с ним тип данных имеет большое значение. Для удобства работы с типами существует конвенция описания типов данных YQL в текстовом виде. Она используется в разных местах документации, а также существует библиотека, предоставляющая функции для построения типа данных по текстовому описанию (например, при ручном описании сигнатуры вызываемого значения) или для сериализации типа данных в строку для отладки.
Ниже описан сам формат текстового представления типов данных.
Общие правила
-
Примитивные типы данных представляются в текстовом виде просто своим именем.
-
Сложный тип данных представляет собой композицию из других типов данных. Если представить эту композицию в виде дерева, то на листьях окажутся примитивные типы данных, а в остальных узлах — контейнеры. Специальные типы данных можно рассматривать как исключение, они могут находиться и там и там.
-
Текстовое представление повторяет структуру этого дерева в порядке от корня к листьям: в каждом узле дерева указывается имя текущего типа данных, а переход на уровень глубже обозначается различными видами скобок.
-
Допустимо использование пробелов и переносов строк, если это облегчает чтение.
-
Если идентификатор состоит не только из английских букв и цифр, то его нужно записывать в одиночных кавычках и использовать C-escaping.
Контейнеры
-
Для указания типов элементов контейнера используются угловые скобки.
Пример:
List<Int32>
. -
Если контейнер предполагает несколько разнородных элементов, то они перечисляются внутри угловых скобок через запятую.
Пример:
Tuple<Int32, String>
. -
Если контейнер предполагает именованные элементы, то вместо типов данных через запятую используются пары из имени и типа через двоеточие.
Пример:
Struct<a:Int32, b:String>
. -
Нижележащий тип контейнера
Variant
выбирается в зависимости от наличия имён в аргументах.Пример:
Variant<Int32, String>
— вариант над кортежем,Variant<a:Int32, b:String>
— вариант над структурой.
Типы, допускающие NULL
-
В терминах YQL это называется
Optional
, в терминах классического SQL — nullable. -
Формально этот тип является контейнером, т.е. запись
Optional<...>
допустима, но обычно вместо неё используется shortcut в виде суффикса из знака вопроса.Пример:
String?
.
Вызываемые значения
-
Базовая форма вызываемых значений выглядит следующим образом:
(arg1, arg2, ...) -> result
.Пример описания сигнатуры функции, принимающей две строки и возвращающей число:
(String, String) -> Int64
. -
Вызываемые значения могут возвращать вызываемые значения, в этом случае они образуют цепочку необходимой длины.
Пример:
(String, String) -> (String, String) -> Int64
. -
Опциональные аргументы должны иметь на верхнем уровне тип
Optional
и обрамляются в квадратные скобки.Пример:
(String, [String?, Double?]) -> Int64
. -
У аргументов вызываемых значений могут быть указаны флаги.
На текущий момент возможен только один флаг —
AutoMap
, который означает, что если в этот аргумент передали NULL, то результат нужно сделать тоже NULL, а саму функцию не запускать.Пример:
(String{Flags: AutoMap}) -> Int64
. -
Если нужен
Optional<Callable<...>>
, то нужно использовать именно такую форму, т.к. знак вопроса в конце относится к результату вызываемого значения.
Ресурсы
-
В отличие от контейнеров, ресурс параметризуется не типом элемента (ресурс является указателем в памяти и YQL ничего не знает о его содержимом), а строковой меткой, которая может использоваться для защиты от передачи ресурсов между несовместимыми функциями.
Пример:
Resource<Foo>
.