Typer
Ett typvärde är ett värde som klassificerar andra värden. Ett värde som klassificeras av en typ sägs överensstämma med den typen. M-typsystemet består av följande typer:
Primitiva typer, som klassificerar primitiva värden (
binary
, ,datetime
date
,datetimezone
,duration
,list
,logical
,null
,number
,record
,text
, ,time
)type
och även innehåller ett antal abstrakta typer (function
,table
,any
ochanynonnull
none
)Posttyper, som klassificerar postvärden baserat på fältnamn och värdetyper
Listtyper, som klassificerar listor med en bastyp för ett objekt
Funktionstyper som klassificerar funktionsvärden baserat på typerna av deras parametrar och returnerar värden
Tabelltyper som klassificerar tabellvärden baserat på kolumnnamn, kolumntyper och nycklar
Nullbara typer, som klassificerar värdet null utöver alla värden som klassificeras av en bastyp
Typtyper som klassificerar värden som är typer
Uppsättningen primitiva typer innehåller typerna av primitiva värden och ett antal abstrakta typer, som är typer som inte unikt klassificerar några värden: function
, table
, any
anynonnull
och none
. Alla funktionsvärden överensstämmer med den abstrakta typen function
, alla tabellvärden till den abstrakta typen table
, alla värden till den abstrakta typen any
, alla icke-null-värden till den abstrakta typen anynonnull
och inga värden till den abstrakta typen none
. Ett uttryck av typen none
måste generera ett fel eller avslutas inte eftersom inget värde kunde skapas som överensstämmer med typen none
. Observera att de primitiva typerna function
och table
är abstrakta eftersom ingen funktion eller tabell är direkt av dessa typer. De primitiva typerna record
och list
är icke-abstrakta eftersom de representerar en öppen post utan definierade fält respektive en lista av typen någon.
Alla typer som inte är medlemmar i den stängda uppsättningen primitiva typer plus deras nullbara motsvarigheter kallas gemensamt anpassade typer. Anpassade typer kan skrivas med hjälp av :type-expression
type-expression:
primary-expression
type
primär typ
typ:
primary-expression
primär typ
primär typ:
primitiv typ
posttyp
listtyp
funktionstyp
tabelltyp
nullable-type
primitiv-typ: en av
any anynonnull binary date datetime datetimezone duration function list logical
none null number record table text time type
Namn av primitiv typ är kontextuella nyckelord som endast identifieras i en typkontext . Användningen av parenteser i en typkontext flyttar grammatiken tillbaka till en kontext för reguljära uttryck, vilket kräver att nyckelordet av typen används för att gå tillbaka till en typkontext. Om du till exempel vill anropa en funktion i en typkontext kan parenteser användas:
type nullable ( Type.ForList({type number}) )
// type nullable {number}
Parenteser kan också användas för att komma åt en variabel vars namn kolliderar med ett primitivt namn :
let record = type [ A = any ] in type {(record)}
// type {[ A = any ]}
I följande exempel definieras en typ som klassificerar en lista med tal:
type { number }
På samma sätt definierar följande exempel en anpassad typ som klassificerar poster med obligatoriska fält med namnet X
och Y
vars värden är tal:
type [ X = number, Y = number ]
Den angivna typen av ett värde hämtas med hjälp av standardbiblioteksfunktionen Value.Type, som du ser i följande exempel:
Value.Type( 2 ) // type number
Value.Type( {2} ) // type list
Value.Type( [ X = 1, Y = 2 ] ) // type record
Operatorn is
används för att avgöra om ett värdes typ är kompatibel med en viss typ, enligt följande exempel:
1 is number // true
1 is text // false
{2} is list // true
Operatorn as
kontrollerar om värdet är kompatibelt med den angivna typen och genererar ett fel om det inte är det. Annars returneras det ursprungliga värdet.
Value.Type( 1 as number ) // type number
{2} as text // error, type mismatch
Observera att operatorerna is
och as
endast accepterar nullbara primitiva typer som sin rätta operande. M tillhandahåller inte sätt att kontrollera värden för överensstämmelse med anpassade typer.
En typ X
är kompatibel med en typ Y
om och endast om alla värden som överensstämmer med också överensstämmer X
med Y
. Alla typer är kompatibla med typen any
och inga typer (men none
själva) är kompatibla med typen none
. Följande diagram visar kompatibilitetsrelationen. (Typkompatibiliteten är reflexiv och transitiv. Den bildar ett gitter med typen any
som överkant och skriver none
som det nedre värdet.) Namnen på abstrakta typer anges i kursiv stil.
Följande operatorer definieras för typvärden:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x ?? y |
Coalesce |
Den interna typen av typvärden är den inbyggda typen type
.
Typer i M-språket utgör en uppdelad hierarki rotad vid typen any
, vilket är den typ som klassificerar alla värden. Alla M-värden överensstämmer med exakt en primitiv undertyp av any
. Den stängda uppsättningen primitiva typer som härleds från typen any
är följande:
type null
, som klassificerar null-värdet.type logical
, som klassificerar värdena true och false.type number
, som klassificerar talvärden.type time
, som klassificerar tidsvärden.type date
, som klassificerar datumvärden.type datetime
, som klassificerar datetime-värden.type datetimezone
, som klassificerar datetimezone-värden.type duration
, som klassificerar varaktighetsvärden.type text
, som klassificerar textvärden.type binary
, som klassificerar binära värden.type type
, som klassificerar typvärden.type list
, som klassificerar listvärden.type record
, som klassificerar postvärden.type table
, som klassificerar tabellvärden.type function
, som klassificerar funktionsvärden.type anynonnull
, som klassificerar alla värden exklusive null.type none
, som inte klassificerar några värden.
Typen any
är abstrakt, klassificerar alla värden i M och alla typer i M är kompatibla med any
. Variabler av typen any
kan bindas till alla möjliga värden. Eftersom any
är abstrakt kan det inte tillskrivas värden, det vill säga inget värde är direkt av typen any
.
Alla värden som är en lista överensstämmer med den inbyggda typen list
, som inte begränsar objekten i ett listvärde.
listtyp:
{
objekttyp }
objekttyp:
typ
Resultatet av utvärderingen av en listtyp är ett listtypsvärde vars bastyp är list
.
Följande exempel illustrerar syntaxen för att deklarera homogena listtyper:
type { number } // list of numbers type
{ record } // list of records type
{{ text }} // list of lists of text values
Ett värde överensstämmer med en listtyp om värdet är en lista och varje objekt i listvärdet överensstämmer med listtypens objekttyp.
Objekttypen för en listtyp anger en bindning: alla objekt i en överensstämmande lista överensstämmer med objekttypen.
Alla värden som är en post överensstämmer med den inbyggda typposten, vilket inte begränsar fältnamnen eller värdena i ett postvärde. Ett värde av posttyp används för att begränsa uppsättningen med giltiga namn samt de typer av värden som tillåts associeras med dessa namn.
posttyp:
[
open-record-marker ]
[
field-specification-listopt ]
[
field-specification-list , open-record-marker ]
field-specification-list:
fältspecifikation
field-specification ,
field-specification-list
fältspecifikation:
optional
opt field-name field-type-specificationopt
field-type-specification:
=
fälttyp
field-type:
type
open-record-marker:
...
Resultatet av utvärderingen av en posttyp är ett typvärde vars bastyp är record
.
Följande exempel illustrerar syntaxen för att deklarera posttyper:
type [ X = number, Y = number]
type [ Name = text, Age = number ]
type [ Title = text, optional Description = text ]
type [ Name = text, ... ]
Posttyper stängs som standard, vilket innebär att ytterligare fält som inte finns i fältpecifieringslistan inte tillåts finnas i överensstämmande värden. Om du inkluderar openrecord-markören i posttypen deklareras typen som öppen, vilket tillåter fält som inte finns i fältspecifikationslistan. Följande två uttryck är likvärdiga:
type record // primitive type classifying all records
type [ ... ] // custom type classifying all records
Ett värde överensstämmer med en posttyp om värdet är en post och varje fältspecifikation i posttypen är uppfylld. En fältspecifikation uppfylls om något av följande är sant:
Ett fältnamn som matchar specifikationens identifierare finns i posten och det associerade värdet överensstämmer med specifikationens typ
Specifikationen är markerad som valfri och inget motsvarande fältnamn finns i posten
Ett överensstämmande värde kan innehålla fältnamn som inte anges i fältspecifikationslistan om och endast om posttypen är öppen.
Alla funktionsvärden överensstämmer med den primitiva typen function
, som inte begränsar typen av funktionens formella parametrar eller funktionens returvärde. Ett anpassat värde av funktionstyp används för att placera typbegränsningar på signaturerna för överensstämmande funktionsvärden.
funktionstyp:
function (
parameter-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:
parameterspecifikation
optional-parameter-specification-list:
optional-parameter-specification
optional-parameter-specification ,
optional-parameter-specification-list
optional-parameter-specification:
optional
parameterspecifikation
parameterspecifikation:
parameter-name parameter-type
function-return-type:
assertion
påstående:
as
nullable-primitive-type
Resultatet av utvärderingen av en funktionstyp är ett typvärde vars bastyp är function
.
Följande exempel illustrerar syntaxen för att deklarera funktionstyper:
type function (x as text) as number
type function (y as number, optional z as text) as any
Ett funktionsvärde överensstämmer med en funktionstyp om returtypen för funktionsvärdet är kompatibel med funktionstypens returtyp och varje parameterspecifikation för funktionstypen är kompatibel med den positionellt motsvarande formella parametern för funktionen. En parameterspecifikation är kompatibel med en formell parameter om den angivna parametertypen är kompatibel med typen av den formella parametern och parameterspecifikationen är valfri om den formella parametern är valfri.
Formella parameternamn ignoreras för att fastställa funktionstypsefterlevnad.
Om du anger en parameter som valfritt implicit kan dess typ vara null. Följande skapar identiska funktionstyper:
type function (optional x as text) as any
type function (optional x as nullable text) as any
Ett tabelltypsvärde används för att definiera strukturen för ett tabellvärde.
tabelltyp:
table
radtyp
radtyp:
[
field-specification-listopt ]
Resultatet av utvärderingen av en tabelltyp är ett typvärde vars bastyp är table
.
Radtypen för en tabell anger kolumnnamnen och kolumntyperna i tabellen som en stängd posttyp. Så att alla tabellvärden överensstämmer med typen table
är dess radtyp typ record
(den tomma öppna posttypen). Därför är typtabellen abstrakt eftersom inget tabellvärde kan ha typens table
radtyp (men alla tabellvärden har en radtyp som är kompatibel med typen table
radtyp). I följande exempel visas konstruktionen av en tabelltyp:
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
Ett tabelltypsvärde innehåller också definitionen av ett tabellvärdes nycklar. En nyckel är en uppsättning kolumnnamn. Högst en nyckel kan anges som tabellens primära nyckel. (I M har tabellnycklar ingen semantisk betydelse. Det är dock vanligt att externa datakällor, till exempel databaser eller OData-feeds, definierar nycklar över tabeller. Power Query använder viktig information för att förbättra prestanda för avancerade funktioner, till exempel anslutningsåtgärder mellan källor.)
Standardbiblioteksfunktionerna Type.TableKeys
, Type.AddTableKey
och Type.ReplaceTableKeys
kan användas för att hämta nycklarna för en tabelltyp, lägga till en nyckel i en tabelltyp och ersätta alla nycklar av en tabelltyp.
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
För alla type T
kan en nullbar variant härledas med hjälp av nullable-type:
nullable-type:
nullable
typ
Resultatet är en abstrakt typ som tillåter värden av typen T eller värdet null
.
42 is nullable number // true null is
nullable number // true
Ascription av type nullable
T reducerar till ascription av type null
eller type
T. (Kom ihåg att nullbara typer är abstrakta och att inget värde kan vara direkt av abstrakt typ.)
Value.Type(42 as nullable number) // type number
Value.Type(null as nullable number) // type null
Standardbiblioteksfunktionerna Type.IsNullable
och Type.NonNullable
kan användas för att testa en typ för nullbarhet och för att ta bort nullbarhet från en typ.
Följande undantag (för alla type T
):
type T
är kompatibel medtype nullable T
Type.NonNullable(type T)
är kompatibel medtype T
Följande är parvis likvärdiga (för alla 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
Ett värdes tillskrivna typ är den typ som ett värde deklareras överensstämma med.
Ett värde kan tillskrivas en typ med hjälp av biblioteksfunktionen Value.ReplaceType
. Den här funktionen returnerar antingen ett nytt värde med typen tillskriven eller genererar ett fel om den nya typen inte är kompatibel med värdet.
När ett värde tilldelas en typ sker endast en begränsad efterlevnadskontroll:
- Den typ som tillskrivas måste vara icke-abstrakt, icke-nullbar och kompatibel med värdets inbyggda (interna) primitiva typ.
- När en anpassad typ som definierar struktur tillskrivas måste den matcha värdets struktur.
- För poster: Typen måste stängas, måste definiera samma antal fält som värdet och får inte innehålla några valfria fält. (Typens fältnamn och fälttyper ersätter de som för närvarande är associerade med posten. Befintliga fältvärden kontrolleras dock inte mot de nya fälttyperna.)
- För tabeller: Typen måste definiera samma antal kolumner som värdet. (Typens kolumnnamn och kolumntyper ersätter de som för närvarande är associerade med tabellen. Befintliga kolumnvärden kontrolleras dock inte mot de nya kolumntyperna.)
- För funktioner: Typen måste definiera samma antal obligatoriska parametrar samt samma antal valfria parametrar som värdet. (Typens parameter och returkontroller, samt dess parameternamn, ersätter de som är associerade med funktionsvärdets aktuella typ. De nya försäkran påverkar dock inte funktionens faktiska beteende.)
- För listor: Värdet måste vara en lista. (Befintliga listobjekt kontrolleras dock inte mot den nya objekttypen.)
Biblioteksfunktioner kan välja att beräkna och tillskriva komplexa typer till resultat baserat på de tillskrivna typerna av indatavärden.
Den angivna typen av ett värde kan hämtas med hjälp av biblioteksfunktionen Value.Type
. Till exempel:
Value.Type( Value.ReplaceType( {1}, type {number} )
// type {number}
Typjämvikt definieras inte i M. En M-implementering kan välja att använda sina egna regler för att utföra likhetsjämförelser mellan typvärden. Jämförelse av två typvärden för likhet bör utvärderas till true
om de anses vara identiska med implementeringen, och false
i annat fall. I båda fallen måste svaret som returneras vara konsekvent om samma två värden jämförs upprepade gånger. Observera att om du jämför vissa identiska typvärden (till exempel (type text) = (type text)
) inom en viss implementering kan det hända true
att andra (till exempel (type [a = text]) = (type [a = text])
) inte jämförs.
Kompatibilitet mellan en viss typ och en nullbar primitiv typ kan fastställas med hjälp av biblioteksfunktionen Type.Is
, som accepterar ett godtyckligt typvärde som det första och ett nullbart primitivt typvärde som sitt andra 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
Det finns inget stöd i M för att fastställa kompatibiliteten för en viss typ med en anpassad typ.
Standardbiblioteket innehåller en samling funktioner för att extrahera de definierande egenskaperna från en anpassad typ, så specifika kompatibilitetstester kan implementeras som M-uttryck. Nedan visas några exempel. Se M-biblioteksspecifikationen för fullständig information.
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