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

Введение

Так как YQL является строго типизированной системой, во многих аспектах работы с ней тип данных имеет большое значение. Для удобства работы с ними, существует конвенция описания типов данных YQL в текстовом виде. Она используется в разных местах документации, а также есть библиотека, предоставляющая функции для построения типа данных по такому описанию (например, при ручном описании сигнатуры вызываемого значения) или для сериализации типа данных в строку для отладки.

Список функций для работы с типами данных описаны в статье Функции для работы с типами, а ниже описан сам формат текстового представления типов данных.

Общие правила

  • За исключением примитивных типов данных (числа, строки и т.п.), которые представляются в текстовом виде просто своим именем, конкретный тип данных представляет собой композицию из других типов данных. Если представить эту композицию в виде дерева, то на листьях окажутся примитивные типы данных, а в остальных узлах — контейнеры. Специальные типы данных можно рассматривать как исключение, они могут находиться и там и там.
  • Текстовое представление повторяет структуру этого дерева в порядке от корня к листьям: в каждом узле дерева указывается имя текущего типа данных, а переход на уровень глубже обозначается тем или иным видом скобок.
  • Список примитивных типов данных, всех видов контейнеров и специальных типов данных представлен в начале основного руководства пользователя.
  • Допустимо использование пробелов и переносов строк, если это улучшает читабельность.
  • Если идентификатор состоит не только из английских букв и цифр, то его нужно записывать в одиночных кавычках и использовать C-escaping.

Контейнеры

  • Для указания типов элементов контейнера используются угловые скобки. Пример: List<Int32>.
  • Если контейнер предполагает несколько разнородных элементов, то они перечисляются внутри угловых скобок через запятую. Пример: Tuple<Int32,String>.
  • Если контейнер предполагает именованные элементы, то вместо просто типов данных через запятую используются пары из имени и типа через двоеточие. Пример: Struct<a:Int32,b:String>.
  • Низлежащий тип для контейнера вариант выбирается в зависимости от наличия имён в аргументах. Пример: 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>.