Typy
Hodnota typu je hodnota, která klasifikuje jiné hodnoty. Hodnota klasifikovaná typem je označena tak, aby odpovídala danému typu. Systém typů M se skládá z následujících typů typů:
Primitivní typy, které klasifikují primitivní hodnoty (
binary
, , ,date
datetime
,datetimezone
duration
,list
, ,logical
null
,number
,record
,text
time
) a zahrnují také řadu abstraktních typů (type
,function
,table
any
aanynonnull
)none
Typy záznamů, které klasifikují hodnoty záznamů na základě názvů polí a typů hodnot
Typy seznamů, které klasifikují seznamy pomocí jednoho základního typu položky
Typy funkcí, které klasifikují hodnoty funkcí na základě typů jejich parametrů a návratových hodnot
Typy tabulek, které klasifikují hodnoty tabulky na základě názvů sloupců, typů sloupců a klíčů
Typy s možnou hodnotou null, které kromě všech hodnot klasifikovaných základním typem klasifikují hodnotu null.
Typy typů, které klasifikují hodnoty, které jsou typy
Sada primitivních typů zahrnuje typy primitivních hodnot a řadu abstraktních typů, které jsou typy, které jednoznačně klasifikují žádné hodnoty: function
, table
, any
anynonnull
a none
. Všechny hodnoty funkce odpovídají abstraktnímu typu function
, všechny hodnoty tabulky abstraktnímu typu table
, všechny hodnoty abstraktního typu any
, všechny nenulové hodnoty abstraktního typu anynonnull
a žádné hodnoty abstraktního typu none
. Výraz typu none
musí vyvolat chybu nebo nelze ukončit, protože nelze vytvořit žádnou hodnotu, která odpovídá typu none
. Mějte na paměti, že primitivní typy function
a table
jsou abstraktní, protože žádná funkce nebo tabulka nejsou přímo z těchto typů. Primitivní typy record
a list
nejsou abstraktní, protože představují otevřený záznam bez definovaných polí a seznam typů.
Všechny typy, které nejsou členy uzavřené sady primitivních typů a jejich protějšky s možnou hodnotou null, se souhrnně označují jako vlastní typy. Vlastní typy lze zapsat pomocí type-expression
:
type-expression:
primary-expression
type
primární typ
type:
primary-expression
primární typ
primární typ:
primitivní typ
typ záznamu
list-type
function-type
table-type
nullable-type
primitivní typ: jeden z
any anynonnull binary date datetime datetimezone duration function list logical
none null number record table text time type
Názvy primitivních typů jsou kontextová klíčová slova rozpoznaná pouze v kontextu typu . Použití závorek v kontextu typu přesune gramatiku zpět do kontextu regulárního výrazu, což vyžaduje použití klíčového slova typu k návratu do kontextu typu. Například k vyvolání funkce v kontextu typu lze použít závorky:
type nullable ( Type.ForList({type number}) )
// type nullable {number}
Závorky lze použít také pro přístup k proměnné, jejíž název koliduje s primitivním názvem typu :
let record = type [ A = any ] in type {(record)}
// type {[ A = any ]}
Následující příklad definuje typ, který klasifikuje seznam čísel:
type { number }
Podobně následující příklad definuje vlastní typ, který klasifikuje záznamy s povinnými poli pojmenovanými X
a Y
jejichž hodnoty jsou čísla:
type [ X = number, Y = number ]
Přiřazený typ hodnoty se získá pomocí standardní funkce knihovny Value.Type, jak je znázorněno v následujících příkladech:
Value.Type( 2 ) // type number
Value.Type( {2} ) // type list
Value.Type( [ X = 1, Y = 2 ] ) // type record
Operátor is
slouží k určení, jestli je typ hodnoty kompatibilní s daným typem, jak je znázorněno v následujících příkladech:
1 is number // true
1 is text // false
{2} is list // true
Operátor as
zkontroluje, jestli je hodnota kompatibilní s daným typem, a pokud není, vyvolá chybu. V opačném případě vrátí původní hodnotu.
Value.Type( 1 as number ) // type number
{2} as text // error, type mismatch
Všimněte si, že operátory a is
operátory as
přijímají jako pravý operand pouze primitivní typy s možnou hodnotou null. M neposkytuje prostředky ke kontrole shody hodnot s vlastními typy.
Typ X
je kompatibilní s typemY
, pokud a pouze pokud všechny hodnoty, které odpovídají X
také .Y
Všechny typy jsou kompatibilní s typem any
a žádné typy (ale none
samotné) jsou kompatibilní s typem none
. Následující graf ukazuje vztah kompatibility. (Kompatibilita typu je reflexní a tranzitivní. Tvoří mřížku s typem any
jako horní a jako none
nejnižší hodnotu.) Názvy abstraktních typů jsou nastavené kurzívou.
Pro hodnoty typu jsou definovány následující operátory:
Operátor | Výsledek |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x ?? y |
Coalesce |
Nativní typ hodnot typu je vnitřní typ type
.
Primitivní typy
Typy v jazyce M tvoří nesouvislou hierarchii kořene typu any
, což je typ, který klasifikuje všechny hodnoty. Jakákoli hodnota jazyka M odpovídá přesně jednomu primitivnímu podtypu any
. Uzavřená sada primitivních typů odvozených z typu any
je následující:
-
type null
, která klasifikuje hodnotu null. -
type logical
, která klasifikuje hodnoty true a false. -
type number
, který klasifikuje číselné hodnoty. -
type time
, který klasifikuje časové hodnoty. -
type date
, který klasifikuje hodnoty kalendářních dat. -
type datetime
, který klasifikuje hodnoty datetime. -
type datetimezone
, který klasifikuje hodnoty datetimezone. -
type duration
, který klasifikuje hodnoty doby trvání. -
type text
, který klasifikuje textové hodnoty. -
type binary
, který klasifikuje binární hodnoty. -
type type
, který klasifikuje hodnoty typu. -
type list
, který klasifikuje hodnoty seznamu. -
type record
, který klasifikuje hodnoty záznamů. -
type table
, která klasifikuje hodnoty tabulky. -
type function
, který klasifikuje hodnoty funkce. -
type anynonnull
, která klasifikuje všechny hodnoty s výjimkou hodnoty null. -
type none
, který klasifikuje žádné hodnoty.
Libovolný typ
Typ any
je abstraktní, klasifikuje všechny hodnoty v jazyce M a všechny typy v jazyce M jsou kompatibilní s any
. Proměnné typu any
mohou být vázány na všechny možné hodnoty. Vzhledem k tomu any
, že je abstraktní, nelze ji připsat k hodnotám – to znamená, že žádná hodnota není přímo typu any
.
Typy seznamů
Jakákoli hodnota, která je seznamem, odpovídá vnitřnímu typu list
, který neukládá žádná omezení pro položky v hodnotě seznamu.
typ seznamu:
{
item-type}
item-type:
typ
Výsledkem vyhodnocení typu seznamu je hodnota typu seznamu, jejíž základní typ je list
.
Následující příklady ilustrují syntaxi pro deklarování homogenních typů seznamů:
type { number } // list of numbers type
{ record } // list of records type
{{ text }} // list of lists of text values
Hodnota odpovídá typu seznamu, pokud je hodnota seznamem a každá položka v této hodnotě seznamu odpovídá typu položky typu seznamu.
Typ položky typu seznamu označuje vazbu: všechny položky odpovídajícího seznamu odpovídají typu položky.
Typy záznamů
Jakákoli hodnota, která je záznamem, odpovídá vnitřnímu záznamu typu, který neukládá žádná omezení názvů polí nebo hodnot v hodnotě záznamu. Hodnota typu záznamu slouží k omezení sady platných názvů a typů hodnot, které mají být k těmto názvům přidruženy.
typ záznamu:
[
open-record-marker]
[
field-specification-listopt]
[
field-specification-list , open-record-marker]
field-specification-list:
specifikace pole
field-specification,
field-specification-list
specifikace pole:
optional
opt field-name field-type-specificationopt
specifikace typu pole:
=
typ pole
typ pole:
type
open-record-marker:
...
Výsledkem vyhodnocení typu záznamu record
Následující příklady ilustrují syntaxi deklarování typů záznamů:
type [ X = number, Y = number]
type [ Name = text, Age = number ]
type [ Title = text, optional Description = text ]
type [ Name = text, ... ]
Typy záznamů jsou ve výchozím nastavení zavřené, což znamená, že další pole, která nejsou v seznamu polí, nesmí být v odpovídajících hodnotách přítomna. Zahrnutí značky openrecord-marker v typu záznamu deklaruje typ, který má být otevřen, což umožňuje pole, která nejsou přítomna v seznamu specifikací polí. Následující dva výrazy jsou ekvivalentní:
type record // primitive type classifying all records
type [ ... ] // custom type classifying all records
Hodnota odpovídá typu záznamu, pokud je hodnota záznamem a každá specifikace pole v typu záznamu je splněna. Specifikace pole je splněna, pokud platí některá z následujících možností:
Název pole odpovídající identifikátoru specifikace existuje v záznamu a přidružená hodnota odpovídá typu specifikace.
Specifikace je označena jako volitelná a v záznamu se nenajde žádný odpovídající název pole.
Odpovídající hodnota může obsahovat názvy polí, které nejsou uvedené v seznamu specifikací polí, pokud je otevřený a pouze pokud je typ záznamu otevřený.
Typy funkcí
Jakákoli hodnota funkce odpovídá primitivnímu typu function
, který neukládá žádná omezení typů formálních parametrů funkce nebo návratové hodnoty funkce. Vlastní hodnota typu funkce slouží k umístění omezení typů na podpisy vyhovujících hodnot funkce.
function-type:
function (
parametr-specification-listopt)
function-return-type
parameter-specification-list:
required-parameter-specification-list
required-parameter-specification-list,
optional-parameter-specification-list
optional-parameter-specification-list
required-parameter-specification-list:
required-parameter-specification
required-parameter-specification,
required-parameter-specification-list
required-parameter-specification:
parametr-specification
optional-parameter-specification-list:
optional-parameter-specification
optional-parameter-specification,
optional-parameter-specification-list
optional-parameter-specification:
optional
parametr-specification
parametr-specification:
parameter-name parameter-type
function-return-type:
assertion
tvrzení:
as
nullable-primitive-type
Výsledkem vyhodnocení typu funkce je hodnota typu typu, jejíž základní typ je function
.
Následující příklady ilustrují syntaxi deklarování typů funkcí:
type function (x as text) as number
type function (y as number, optional z as text) as any
Hodnota funkce odpovídá typu funkce, pokud je návratový typ hodnoty funkce kompatibilní s návratovým typem typu funkce a každá specifikace parametru typu funkce je kompatibilní s pozičním formálním parametrem funkce. Specifikace parametru je kompatibilní s formálním parametrem, pokud je zadaný typ parametru kompatibilní s typem formálního parametru a specifikace parametru je nepovinná, pokud je formální parametr volitelný.
Formální názvy parametrů jsou ignorovány pro účely určení shody typu funkce.
Zadání parametru jako volitelné implicitně způsobí, že jeho typ má hodnotu null. Následující typy funkcí vytvářejí identické typy:
type function (optional x as text) as any
type function (optional x as nullable text) as any
Typy tabulek
Hodnota typu tabulky slouží k definování struktury hodnoty tabulky.
typ tabulky:
table
typ řádku
typ řádku:
[
field-specification-listopt]
Výsledkem vyhodnocení typu tabulky je hodnota typu, jejíž základní typ je table
.
Typ řádku tabulky určuje názvy sloupců a typy sloupců tabulky jako uzavřený typ záznamu. Aby všechny hodnoty tabulky odpovídaly typu table
, typ řádku je typ record
(prázdný typ otevřeného záznamu). Tabulka typů je tedy abstraktní, protože žádná hodnota tabulky nemůže mít table
typ řádku (ale všechny hodnoty tabulky mají typ řádku, který je kompatibilní s typem table
řádku typu). Následující příklad ukazuje výstavbu typu tabulky:
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
Hodnota typu tabulky také nese definici klíčů hodnoty tabulky. Klíč je sada názvů sloupců. Jako primární klíč tabulky lze určit maximálně jeden klíč. (V jazyce M nemají klíče tabulky žádný sémantický význam. U externích zdrojů dat, jako jsou databáze nebo datové kanály OData, je ale běžné definovat klíče nad tabulkami. Power Query používá klíčové informace ke zlepšení výkonu pokročilých funkcí, jako jsou operace spojení mezi zdroji.)
Standardní funkce Type.TableKeys
knihovny , Type.AddTableKey
a Type.ReplaceTableKeys
lze použít k získání klíčů typu tabulky, přidat klíč k typu tabulky a nahradit všechny klíče typu tabulky, v uvedeném pořadí.
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
Typy s povolenou hodnotou Null
Pro libovolnou type T
variantu s možnou hodnotou null lze odvodit pomocí typu nullable:
nullable-type:
nullable
typ
Výsledek je abstraktní typ, který umožňuje hodnoty typu T nebo hodnota null
.
42 is nullable number // true null is
nullable number // true
Ascription T type nullable
se snižuje na index nebo type null
type
T. (Vzpomeňte si, že typy s možnou hodnotou null jsou abstraktní a žádná hodnota nemůže být přímo abstraktního typu.)
Value.Type(42 as nullable number) // type number
Value.Type(null as nullable number) // type null
Standardní funkce Type.IsNullable
knihovny a Type.NonNullable
lze je použít k otestování typu s možnou hodnotou null a k odebrání hodnoty nullability z typu.
Následující blokování (pro libovolnou type T
):
-
type T
je kompatibilní stype nullable T
-
Type.NonNullable(type T)
je kompatibilní stype T
Toto jsou párové ekvivalenty (pro libovolnou 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
Přiřazený typ hodnoty
Přiřazený typ hodnoty je typ , ke kterému je hodnota deklarována tak, aby odpovídala .
Hodnota může být přiřazena typ pomocí funkce Value.ReplaceType
knihovny . Tato funkce buď vrátí novou hodnotu s přiřazeným typem, nebo vyvolá chybu, pokud je nový typ nekompatibilní s hodnotou.
Pokud je hodnota přiřazena typu, dojde pouze k omezené kontrole shody:
- Přiřazený typ musí být non-abstraktní, non-nullable a kompatibilní s vnitřní (nativní) primitivní typ hodnoty.
- Pokud je přiřazen vlastní typ, který definuje strukturu, musí odpovídat struktuře hodnoty.
- Pro záznamy: Typ musí být uzavřen, musí definovat stejný počet polí jako hodnota a nesmí obsahovat žádná nepovinná pole. (Názvy polí a typy polí typu nahradí ty, které jsou aktuálně přidružené k záznamu. Existující hodnoty polí však nebudou kontrolovány u nových typů polí.)
- Pro tabulky: Typ musí definovat stejný počet sloupců jako hodnota. (Názvy sloupců a typy sloupců typu nahradí ty, které jsou aktuálně přidružené k tabulce. Existující hodnoty sloupců se však nebudou kontrolovat u nových typů sloupců.)
- Pro funkce: Typ musí definovat stejný počet požadovaných parametrů a stejný počet volitelných parametrů jako hodnota. (Parametr typu a návratové kontrolní výrazy a jeho názvy parametrů nahradí ty, které jsou přidruženy k aktuálnímu typu hodnoty funkce. Nové kontrolní výrazy však nebudou mít žádný vliv na skutečné chování funkce.)
- Pro seznamy: Hodnota musí být seznam. (Existující položky seznamu se však nebudou kontrolovat u nového typu položky.)
Funkce knihovny se můžou rozhodnout vypočítat a připsat komplexní typy výsledkům na základě přiřazených typů vstupních hodnot.
Přiřazený typ hodnoty lze získat pomocí funkce Value.Type
knihovny . Příklad:
Value.Type( Value.ReplaceType( {1}, type {number} )
// type {number}
Ekvivalence typů a kompatibilita
V jazyce M není definována ekvivalence typů. Implementace jazyka M se může volitelně rozhodnout použít vlastní pravidla k porovnání rovnosti mezi hodnotami typu. Porovnání dvou hodnot typu rovnosti by se mělo vyhodnotit true
, jestli jsou považovány za stejné implementací, a false
jinak. V oboupřípadechch Všimněte si, že v rámci dané implementace může porovnání některých identických hodnot typu (například (type text) = (type text)
) vrátit true
, zatímco porovnávání jiných (například (type [a = text]) = (type [a = text])
) nemusí.
Kompatibilita mezi daným typem a primitivním typem s možnou hodnotou null lze určit pomocí funkce Type.Is
knihovny, která přijímá libovolnou hodnotu typu jako první a hodnotu primitivního typu s možnou hodnotou null jako druhý argument:
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
V jazyce M není podporována kompatibilita daného typu s vlastním typem.
Standardní knihovna obsahuje kolekci funkcí pro extrakci definujících charakteristik z vlastního typu, takže je možné implementovat specifické testy kompatibility jako výrazy M. Níže jsou uvedeny některé příklady; Úplné podrobnosti najdete ve specifikaci knihovny 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