Работа с текстовым представлением типов данных

Введение

Так как 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>.