Поделиться через


Типы

Значение типа — это значение, которое классифицирует другие значения. Значение, классифицируемые типом, как сообщается , соответствует такому типу. Система типов M состоит из следующих типов:

  • Примитивные типы, которые классифицируют примитивные значения (binary, nulldurationdatedatetimezonetypedatetimenumberlistrecordtimelogicaltext) и включают ряд абстрактных типов (function, table, anyanynonnull и)none

  • Типы записей, которые классифицируют значения записей на основе имен полей и типов значений

  • Типы списков, которые классифицируют списки с помощью базового типа одного элемента

  • Типы функций, которые классифицируют значения функций на основе типов их параметров и возвращаемых значений

  • Типы таблиц, которые классифицируют значения таблиц на основе имен столбцов, типов столбцов и ключей

  • Типы, допускающие значение NULL, классифицируют значение NULL в дополнение ко всем значениям, классифицированным базовым типом.

  • Типы типов, которые классифицируют значения, которые являются типами

Набор примитивных типов включает типы примитивных значений, а также ряд абстрактных типов, которые являются типами, которые не однозначно классифицируют любые значения: function, table, anyanynonnull и none. Все значения функций соответствуют абстрактным типамfunction, все табличные значения абстрактного типа, все значения абстрактного типаtableany, все значения, не допускающиеся null, к абстрактным типуanynonnull, и никакие значения абстрактного типаnone. Выражение типа none должно вызвать ошибку или завершить работу, так как не удалось создать значение, соответствующее типу none. Обратите внимание, что примитивные типы function и table являются абстрактными, так как функция или таблица не являются непосредственно этими типами, соответственно. Примитивные типы record и list являются не абстрактными, так как они представляют открытую запись без определенных полей и список типов соответственно.

Все типы, которые не являются членами закрытого набора примитивных типов, а также их допустимые значения NULL, называются пользовательскими типами. Пользовательские типы можно записать с помощью :type-expression

выражение-типа:
      основное-выражение

      typeprimary-type
тип:
      основное-выражение
      основной-тип
основной-тип:
      тип-примитива
      тип-записи
      тип-списка
      тип-функции
      тип-таблицы
      тип-допускающий-значение-NULL
тип-примитива:
один-из
      any anynonnull binary date datetime datetimezone duration function list logical
      none null number record table text time type

Имена примитивных типов — это контекстные ключевые слова , распознанные только в контексте типа . Использование скобок в контексте типа перемещает грамматику обратно в контекст регулярного выражения, требуя использования ключевого слова типа для возврата в контекст типа. Например, чтобы вызвать функцию в контексте типа , можно использовать скобки:

type nullable ( Type.ForList({type number}) )   
// type nullable {number}

Скобки также можно использовать для доступа к переменной, имя которой сталкивается с именем примитивного типа :

let  record = type [ A = any ]  in  type {(record)} 
// type {[ A = any ]}

В следующем примере определяется тип, который классифицирует список чисел:

type { number }

Аналогичным образом, в следующем примере определяется пользовательский тип, который классифицирует записи с обязательными полями с именами X и Y значениями которых являются числами:

type [ X = number, Y = number ]

Приписываемый тип значения получается с помощью функции стандартной библиотеки Value.Type, как показано в следующих примерах:

Value.Type( 2 )                 // type number 
Value.Type( {2} )               // type list 
Value.Type( [ X = 1, Y = 2 ] )  // type record

Оператор is используется для определения совместимости типа значения с заданным типом, как показано в следующих примерах:

1 is number          // true 
1 is text            // false 
{2} is list          // true

Оператор as проверяет, совместимо ли значение с заданным типом, и вызывает ошибку, если это не так. В противном случае возвращает исходное значение.

Value.Type( 1 as number )   // type number 
{2} as text                 // error, type mismatch

Обратите внимание, что операторы as принимают только допустимые is типы примитивов NULL в качестве правого операнда. M не предоставляет средства проверки значений соответствия пользовательским типам.

Тип X совместим с типомY, если и только если все значения, соответствующие требованиям, также соответствуютYX. Все типы совместимы с типом any , а типы (но none сами по себе) совместимы с типом none. На следующем графике показана связь совместимости. (Совместимость типов является рефлексивной и транзитивной. Она формирует решетку с типом any в качестве верхнего значения и типом none в качестве нижнего значения.) Имена абстрактных типов выделены курсивом.

Совместимость типов

Для значений типов определены следующие операторы:

Оператор Результат
x = y Equal
x <> y Not equal
x ?? y Coalesce

Собственный тип значений типов — это встроенный тип type.

Примитивные типы

Типы на языке M образуют несвязанную иерархию, корневую в типе any, которая является типом, который классифицирует все значения. Любое значение M соответствует точно одному примитивному подтипу any. Закрытый набор примитивных типов, производных от типа any , выглядит следующим образом:

  • type null, который классифицирует значение NULL.
  • type logical, который классифицирует значения true и false.
  • type number, который классифицирует значения чисел.
  • type time, который классифицирует значения времени.
  • type date, который классифицирует значения даты.
  • type datetime, который классифицирует значения datetime.
  • type datetimezone, который классифицирует значения datetimezone.
  • type duration, который классифицирует значения длительности.
  • type text, который классифицирует текстовые значения.
  • type binary, который классифицирует двоичные значения.
  • type type, который классифицирует значения типов.
  • type list, который классифицирует значения списка.
  • type record, который классифицирует значения записей.
  • type table, который классифицирует значения таблицы.
  • type function, который классифицирует значения функций.
  • type anynonnull, который классифицирует все значения, за исключением NULL.
  • type none, который классифицирует значения без значений.

Любой тип

Тип any является абстрактным, классифицирует все значения в M, а все типы в M совместимы с any. Переменные типа any могут быть привязаны ко всем возможным значениям. Так как any является абстрактным, он не может быть приписан значениям. То есть, никакое значение не может напрямую иметь тип any.

Типы списков

Любое значение, являющееся списком, соответствует встроенному типу list, который не накладывает ограничения на элементы в значении списка.

list-type:
      { Тип элемента }
тип-элемента:
      тип

Результатом оценки типа списка является значение типа списка, базовое тип которого — list.

В следующих примерах показан синтаксис для объявления однородных типов списков:

type { number }        // list of numbers type 
     { record }        // list of records type
     {{ text }}        // list of lists of text values

Значение соответствует типу списка, если значение является списком, и каждый элемент в этом значении списка соответствует типу элемента типа списка.

Тип элемента типа списка указывает на привязку: все элементы соответствующего списка соответствуют типу элемента.

Типы записей

Любое значение, являющееся записью, соответствует записи встроенного типа, которая не ограничивает имена полей или значения в значении записи. Значение типа записи используется для ограничения набора допустимых имен, а также типов значений, которые могут быть связаны с этими именами.

тип записи:
      [open-record-marker ]
      [ выбор спискаспецификаций поля ]
      [ field-specification-list , open-record-marker ]
список-спецификаций-поля:
      спецификация-поля
      field-specification field-specification-list,
спецификация-поля:

      optionalнеобязательно имя-поля спецификация-типа-полянеобязательно
спецификация-типа-поля:

      =тип поля
тип-поля:
      type
маркер-открытой-записи:

      ...

Результатом оценки типа записи является значение типа , базовое тип которого является record.

В следующих примерах показан синтаксис для объявления типов записей:

type [ X = number, Y = number] 
type [ Name = text, Age = number ]
type [ Title = text, optional Description = text ] 
type [ Name = text, ... ]

Типы записей закрываются по умолчанию, то есть дополнительные поля, отсутствующие в списке полей, не могут присутствовать в соответствующих значениях. Включение маркера openrecord в тип записи объявляет тип, который позволяет полям, не присутствующих в списке спецификаций полей. Следующие два выражения эквивалентны:

type record   // primitive type classifying all records 
type [ ... ]  // custom type classifying all records

Значение соответствует типу записи, если значение является записью, а каждая спецификация поля в типе записи удовлетворена. Спецификация поля удовлетворяется, если одно из следующих значений имеет значение true:

  • Имя поля, соответствующее идентификатору спецификации, существует в записи, а связанное значение соответствует типу спецификации.

  • Спецификация помечена как необязательное, и в записи не найдено соответствующее имя поля.

Соответствующее значение может содержать имена полей, не перечисленные в списке спецификаций полей, если и только если тип записи открыт.

Типы функций

Любое значение функции соответствует примитивному типу function, который не накладывает никаких ограничений на типы формальных параметров функции или возвращаемое значение функции. Настраиваемое значение типа функции используется для размещения ограничений типов на подписи соответствующих значений функций.

тип функции:
      function ( параметр-спецификация-listopt ) function-return-type
список-спецификаций-параметров:
      список-спецификаций-обязательных-параметров
      required-parameter-specification-list
, optional-parameter-specification-list
      список-спецификаций-необязательных-параметров
список-спецификаций-обязательных-параметров:
      спецификация-обязательных-параметров
      required-parameter-specification
, required-parameter-specification-list
спецификация-обязательных-параметров:
      спецификация-параметров
список-спецификаций-необязательных-параметров:
      спецификация-необязательных-параметров
      необязательный-параметр-спецификация
, необязательный-параметр-list
спецификация-необязательных-параметров:

      optionalспецификация параметра
спецификация-параметров:
      имя-параметра тип-параметра
тип-возвращаемого-значения-функции:
      assertion
assertion:

      as nullable-primitive-type

Результатом оценки типа функции является значение типа, базовое тип которого является function.

В следующих примерах показан синтаксис для объявления типов функций:

type function (x as text) as number 
type function (y as number, optional z as text) as any

Значение функции соответствует типу функции, если возвращаемый тип значения функции совместим с возвращаемым типом функции, и каждая спецификация параметра типа функции совместима с позиционально соответствующим формальным параметром функции. Спецификация параметров совместима с формальным параметром, если указанный тип типа параметров совместим с типом формального параметра, а спецификация параметра является необязательной, если формальный параметр является необязательным.

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

Указание параметра как необязательного неявного делает его тип null. Следующие типы функций создают идентичные:

type function (optional x as text) as any
type function (optional x as nullable text) as any

Типы таблиц

Значение типа таблицы используется для определения структуры табличного значения.

table-type:
      tableтип строки
тип-строки:

      [ выбор спискаспецификаций поля ]

Результатом оценки табличного типа является значение типа, базовое тип которого является table.

Тип строки таблицы указывает имена столбцов и типы столбцов таблицы как закрытый тип записи. Таким образом, все значения таблицы соответствуют типу table, его тип строки имеет тип record (пустой открытый тип записи). Таким образом, таблица типов абстрактна, так как значение таблицы не может иметь тип строки типа table(но все значения таблицы имеют тип строки, совместимый с типом строки типа tableстроки). В следующем примере показана конструкция типа таблицы:

type table [A = text, B = number, C = binary] 
// a table type with three columns named A, B, and C 
// of column types text, number, and binary, respectively

Значение табличного типа также содержит определение ключей табличного значения. Ключ — это набор имен столбцов. По крайней мере один ключ можно назначить в качестве первичного ключа таблицы. (В языке M ключи таблиц не имеют семантического значения. Однако обычно для внешних источников данных, таких как базы данных или веб-каналы OData, определяются ключи в таблицах. Power Query использует сведения о ключе для повышения производительности расширенных функций, таких как операции объединения между источниками.)

Стандартные функции Type.TableKeysType.AddTableKeyбиблиотеки и Type.ReplaceTableKeys могут использоваться для получения ключей типа таблицы, добавления ключа в тип таблицы и замены всех ключей типа таблицы соответственно.

Type.AddTableKey(tableType, {"A", "B"}, false) 
// add a non-primary key that combines values from columns A and B 
Type.ReplaceTableKeys(tableType, {}) 
// returns type value with all keys removed

Типы, допускающие значения NULL

Для любого type T можно получить вариант, допускающий значение NULL, с помощью типа, допускающего значение NULL:

Тип, допускающий значение NULL:
      nullableтип

Результатом является абстрактный тип, позволяющий значения типа T или значения null.

42 is nullable number             // true null is
nullable number                   // true

Аскрипция T уменьшается до аскрипции type nullable type null или type T. (Помните, что типы, допускающие значение NULL, являются абстрактными, и значение не может быть непосредственно абстрактным типом.)

Value.Type(42 as nullable number)       // type number
Value.Type(null as nullable number)     // type null

Стандартные функции Type.IsNullable библиотеки и Type.NonNullable могут использоваться для проверки типа для допустимости null и удаления значения NULL из типа.

Следующее удержание (для любого type T):

  • type T совместим с type nullable T
  • Type.NonNullable(type T) совместим с type T

Ниже приведены парные эквиваленты (для любого type T):

    type nullable any
    any

    Type.NonNullable(type any)
    type anynonnull

    type nullable none
    type null

    Type.NonNullable(type null)
    type none

    type nullable nullable T
    type nullable T

    Type.NonNullable(Type.NonNullable(type T))
    Type.NonNullable(type T)

    Type.NonNullable(type nullable T)
    Type.NonNullable(type T)

    type nullable (Type.NonNullable(type T))
    type nullable T

Аписанный тип значения

Указанный тип значения — это тип, к которому объявляется значение, соответствующее.

Значение может быть написано типом с помощью функции Value.ReplaceTypeбиблиотеки. Эта функция возвращает новое значение с введенным типом или вызывает ошибку, если новый тип несовместим со значением.

При указании значения типа происходит только ограниченная проверка соответствия:

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

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

Атрибутированный тип значения может быть получен с помощью функции Value.Typeбиблиотеки. Например:

Value.Type( Value.ReplaceType( {1}, type {number} ) 
// type {number}

Эквивалентность типов и совместимость

Эквивалентность типов не определена в M. Реализация M может при необходимости использовать собственные правила для сравнения равенства между значениями типов. Сравнение двух значений типа для равенства должно оцениваться, true если они считаются идентичными реализации и false в противном случае. В любом случае возвращаемый ответ должен быть согласован, если одно и то же два значения многократно сравниваются. Обратите внимание, что в рамках данной реализации сравнение некоторых идентичных значений типов (например (type text) = (type text)) может возвращать true, сравнивая другие (например (type [a = text]) = (type [a = text]), не могут).

Совместимость между заданным типом и примитивным типом, допускаемым значением NULL, можно определить с помощью функции Type.Isбиблиотеки, которая принимает значение произвольного типа в качестве первого и значения примитивного типа null в качестве второго аргумента:

Type.Is(type text, type nullable text)  // true 
Type.Is(type nullable text, type text)  // false 
Type.Is(type number, type text)         // false 
Type.Is(type [a=any], type record)      // true 
Type.Is(type [a=any], type list)        // false

В M не поддерживается определение совместимости заданного типа с пользовательским типом.

Стандартная библиотека включает коллекцию функций для извлечения определяющих характеристик из пользовательского типа, поэтому конкретные тесты совместимости можно реализовать как выражения M. Ниже приведены некоторые примеры. Дополнительные сведения см. в спецификации библиотеки M.

Type.ListItem( type {number} ) 
  // type number 
Type.NonNullable( type nullable text ) 
  // type text 
Type.RecordFields( type [A=text, B=time] ) 
  // [ A = [Type = type text, Optional = false], 
  //   B = [Type = type time, Optional = false] ] 
Type.TableRow( type table [X=number, Y=date] ) 
  // type [X = number, Y = date] 
Type.FunctionParameters(
        type function (x as number, optional y as text) as number) 
  // [ x = type number, y = type nullable text ] 
Type.FunctionRequiredParameters(
        type function (x as number, optional y as text) as number) 
  // 1 
Type.FunctionReturn(
        type function (x as number, optional y as text) as number) 
  // type number