Typer
En typeværdi er en værdi, der klassificerer andre værdier. En værdi, der er klassificeret af en type, siges at være i overensstemmelse med denne type. M-typesystemet består af følgende typer:
Primitive typer, som klassificerer primitive værdier (
binary
,date
,datetime
,duration
datetimezone
,list
,logical
,null
,number
,record
,text
, ,time
)type
og også omfatter en række abstrakte typer (function
,table
,any
oganynonnull
none
)Posttyper, der klassificerer postværdier baseret på feltnavne og værdityper
Listetyper, der klassificerer lister ved hjælp af en basistype for et enkelt element
Funktionstyper, der klassificerer funktionsværdier baseret på typerne af deres parametre og returværdier
Tabeltyper, der klassificerer tabelværdier baseret på kolonnenavne, kolonnetyper og nøgler
Null-typer, der klassificerer værdien null ud over alle de værdier, der er klassificeret af en basistype
Typetyper, der klassificerer værdier, der er typer
Sættet af primitive typer omfatter typerne af primitive værdier og en række abstrakte typer, som er typer, der ikke entydigt klassificerer nogen værdier: function
, table
, any
anynonnull
og none
. Alle funktionsværdier er i overensstemmelse med den abstrakte type function
, alle tabelværdier til den abstrakte type table
, alle værdier til den abstrakte type any
, alle ikke-null-værdier til den abstrakte type anynonnull
og ingen værdier til den abstrakte type none
. Et udtryk af typen none
skal udløse en fejl eller ikke kunne afsluttes, da der ikke kan oprettes en værdi, der er i overensstemmelse med typen none
. Bemærk, at de primitive typer function
og table
er abstrakte, fordi ingen funktion eller tabel er direkte af disse typer. De primitive typer record
og list
er ikke-abstrakte, fordi de repræsenterer en åben post uden definerede felter og en liste af typen nogen.
Alle typer, der ikke er medlemmer af det lukkede sæt af primitive typer plus deres modparter, der kan være null, kaldes samlet for brugerdefinerede typer. Brugerdefinerede typer kan skrives ved hjælp af :type-expression
type-expression:
primary-expression
type
primary-type
slags:
primary-expression
primary-type
primary-type:
primitiv type
posttype
listetype
funktionstype
tabeltype
nullable-type
primitiv-type: en af
any anynonnull binary date datetime datetimezone duration function list logical
none null number record table text time type
Navne på primitive typer er kontekstafhængige nøgleord, der kun genkendes i en typekontekst . Brugen af parenteser i en typekontekst flytter grammatikken tilbage til en regulær udtrykskontekst, hvilket kræver brug af typenøgleordet for at flytte tilbage til en typekontekst. Hvis du f.eks. vil aktivere en funktion i en typekontekst , kan parenteser bruges:
type nullable ( Type.ForList({type number}) )
// type nullable {number}
Parenteser kan også bruges til at få adgang til en variabel, hvis navn kolliderer med et navn af primitiv type :
let record = type [ A = any ] in type {(record)}
// type {[ A = any ]}
I følgende eksempel defineres en type, der klassificerer en liste over tal:
type { number }
På samme måde definerer følgende eksempel en brugerdefineret type, der klassificerer poster med obligatoriske felter med navnet X
, og Y
hvis værdier er tal:
type [ X = number, Y = number ]
Den tilskrevne type af en værdi hentes ved hjælp af standardbiblioteksfunktionen Value.Type, som vist i følgende eksempler:
Value.Type( 2 ) // type number
Value.Type( {2} ) // type list
Value.Type( [ X = 1, Y = 2 ] ) // type record
Operatoren is
bruges til at bestemme, om en værdis type er kompatibel med en given type, som vist i følgende eksempler:
1 is number // true
1 is text // false
{2} is list // true
Operatoren as
kontrollerer, om værdien er kompatibel med den angivne type, og udløser en fejl, hvis den ikke er. Ellers returneres den oprindelige værdi.
Value.Type( 1 as number ) // type number
{2} as text // error, type mismatch
Bemærk, at operatorerne is
og as
kun accepterer primitive typer, der kan være null, som deres rette operand. M giver ikke mulighed for at kontrollere værdier for overensstemmelse med brugerdefinerede typer.
En type X
er kompatibel med en type Y
, hvis og kun hvis alle værdier, der er i overensstemmelse med X
, også er i overensstemmelse med Y
. Alle typer er kompatible med typen any
, og ingen typer (men none
sig selv) er kompatible med typen none
. I følgende graf vises kompatibilitetsrelationen. Typekompatibilitet er refleksiv og transitiv. Det danner et gitter med typen any
øverst og skriv none
som den nederste værdi.) Navnene på abstrakte typer angives med kursiv.
Følgende operatorer er defineret for typeværdier:
Operator | Resultat |
---|---|
x = y |
Lig med |
x <> y |
Ikke lig med |
x ?? y |
Coalesce |
Den oprindelige type af typeværdier er den indbyggede type type
.
Typer i M-sproget udgør et usammenhængende hierarki med rod i typen any
, som er den type, der klassificerer alle værdier. Alle M-værdier er i overensstemmelse med præcis én primitiv undertype af any
. Det lukkede sæt af primitive typer, der er afledt af typen any
, er som følger:
type null
, som klassificerer null-værdien.type logical
, som klassificerer værdierne true og false.type number
, som klassificerer talværdier.type time
, som klassificerer klokkeslætsværdier.type date
, som klassificerer datoværdier.type datetime
, som klassificerer datetime-værdier.type datetimezone
, som klassificerer datetimezone-værdier.type duration
, som klassificerer varighedsværdier.type text
, som klassificerer tekstværdier.type binary
, som klassificerer binære værdier.type type
, som klassificerer typeværdier.type list
, som klassificerer listeværdier.type record
, som klassificerer postværdier.type table
, som klassificerer tabelværdier.type function
, som klassificerer funktionsværdier.type anynonnull
, som klassificerer alle værdier, der udelader null.type none
, som klassificerer ingen værdier.
Typen any
er abstrakt, klassificerer alle værdier i M, og alle typer i M er kompatible med any
. Variabler af typen any
kan bindes til alle mulige værdier. Da any
er abstrakt, kan den ikke tilskrives værdier, dvs. ingen værdi er direkte af typen any
.
Alle værdier, der er en liste, er i overensstemmelse med den indbyggede type list
, som ikke angiver nogen begrænsninger for elementerne i en listeværdi.
listetype:
{
elementtype }
item-type:
slags
Resultatet af evalueringen af en listetype er en listetypeværdi , hvis basistype er list
.
I følgende eksempler illustreres syntaksen for erklæring af homogene listetyper:
type { number } // list of numbers type
{ record } // list of records type
{{ text }} // list of lists of text values
En værdi er i overensstemmelse med en listetype, hvis værdien er en liste, og hvert element i den pågældende listeværdi stemmer overens med listetypens elementtype.
Elementtypen for en listetype angiver en bundet: Alle elementer på en liste, der stemmer overens, er i overensstemmelse med elementtypen.
Alle værdier, der er en post, er i overensstemmelse med den indbyggede typepost, som ikke indeholder nogen begrænsninger for feltnavnene eller værdierne i en postværdi. En posttypeværdi bruges til at begrænse sættet af gyldige navne samt de typer værdier, der må knyttes til disse navne.
record-type:
[
open-record-marker ]
[
field-specification-listopt ]
[
field-specification-list , open-record-marker ]
field-specification-list:
field-specification
field-specification ,
field-specification-list
field-specification:
optional
opt field-name field-type-specificationopt
field-type-specification:
=
felttype
field-type:
type
open-record-marker:
...
Resultatet af evalueringen af en posttype er en typeværdi, hvis basistype er record
.
Følgende eksempler illustrerer syntaksen for erklæring af posttyper:
type [ X = number, Y = number]
type [ Name = text, Age = number ]
type [ Title = text, optional Description = text ]
type [ Name = text, ... ]
Posttyper lukkes som standard, hvilket betyder, at yderligere felter, der ikke findes på feltspecifikationslisten, ikke må være til stede i overensstemmende værdier. Hvis du medtager openrecord-marker i posttypen, erklæres typen åben, hvilket tillader felter, der ikke findes på listen med feltspecifikationer. Følgende to udtryk svarer til hinanden:
type record // primitive type classifying all records
type [ ... ] // custom type classifying all records
En værdi er i overensstemmelse med en posttype, hvis værdien er en post, og hver feltspecifikation i posttypen er opfyldt. En feltspecifikation er opfyldt, hvis et af følgende er sandt:
Der findes et feltnavn, der svarer til specifikationens id, i posten, og den tilknyttede værdi er i overensstemmelse med specifikationens type
Specifikationen er markeret som valgfri, og der blev ikke fundet et tilsvarende feltnavn i posten
En overensstemmende værdi kan indeholde feltnavne, der ikke er angivet på listen med feltspecifikationer, hvis og kun hvis posttypen er åben.
Alle funktionsværdier er i overensstemmelse med den primitive type function
, som ikke angiver nogen begrænsninger for typerne af funktionens formelle parametre eller funktionens returværdi. En brugerdefineret funktionstypeværdi bruges til at angive typebegrænsninger for signaturer for overensstemmende funktionsværdier.
function-type:
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
parameter-specification:
parameter-name parameter-type
function-return-type:
assertion
påstand:
as
nullable-primitive-type
Resultatet af evalueringen af en funktionstype er en typeværdi, hvis basistype er function
.
I følgende eksempler illustreres syntaksen for erklæring af funktionstyper:
type function (x as text) as number
type function (y as number, optional z as text) as any
En funktionsværdi er i overensstemmelse med en funktionstype, hvis funktionsværdiens returtype er kompatibel med funktionstypens returtype, og hver parameterspecifikation for funktionstypen er kompatibel med den positionsmæssigt tilsvarende formelle parameter for funktionen. En parameterspecifikation er kompatibel med en formel parameter, hvis den angivne parametertypetype er kompatibel med typen af den formelle parameter, og parameterspecifikationen er valgfri, hvis den formelle parameter er valgfri.
Formelle parameternavne ignoreres med henblik på at bestemme funktionstypeoverensstemmelse.
Hvis du angiver en parameter som valgfrit, kan typen være null. Følgende opretter identiske funktionstyper:
type function (optional x as text) as any
type function (optional x as nullable text) as any
En tabeltypeværdi bruges til at definere strukturen af en tabelværdi.
table-type:
table
rækketype
row-type:
[
field-specification-listopt ]
Resultatet af evalueringen af en tabeltype er en typeværdi, hvis basistype er table
.
Rækketypen for en tabel angiver kolonnenavnene og kolonnetyperne i tabellen som en lukket posttype. Så alle tabelværdier er i overensstemmelse med typen table
, er rækketypen type record
(den tomme åbne posttype). Typetabellen er derfor abstrakt, da ingen tabelværdi kan have typens table
rækketype (men alle tabelværdier har en rækketype, der er kompatibel med typen table
's rækketype). I følgende eksempel vises oprettelsen af en tabeltype:
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
En tabeltypeværdi indeholder også definitionen af en tabelværdis nøgler. En nøgle er et sæt kolonnenavne. Der kan højst angives én nøgle som tabellens primære nøgle. (I M har tabelnøgler ingen semantisk betydning. Det er dog almindeligt, at eksterne datakilder, f.eks. databaser eller OData-feeds, definerer nøgler over tabeller. Power Query bruger vigtige oplysninger til at forbedre ydeevnen af avancerede funktioner, f.eks. joinhandlinger på tværs af kilder.)
Standardbiblioteksfunktionerne Type.TableKeys
, Type.AddTableKey
og Type.ReplaceTableKeys
kan bruges til at hente nøglerne til en tabeltype, føje en nøgle til en tabeltype og erstatte alle nøgler af en tabeltype.
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
For alle type T
kan en variant, der kan være null, afledes ved hjælp af null-type:
nullable-type:
nullable
slags
Resultatet er en abstrakt type, der tillader værdier af typen T eller værdien null
.
42 is nullable number // true null is
nullable number // true
Ascription af type nullable
T reduceres til ascription af type null
eller type
T. Husk, at null-typer er abstrakte, og at ingen værdi kan være direkte af abstrakt type.
Value.Type(42 as nullable number) // type number
Value.Type(null as nullable number) // type null
Standardbiblioteksfunktionerne Type.IsNullable
og Type.NonNullable
kan bruges til at teste en type for nullability og til at fjerne nullability fra en type.
Følgende venteposition (for enhver type T
):
type T
er kompatibel medtype nullable T
Type.NonNullable(type T)
er kompatibel medtype T
Følgende svarer parvis (for enhver 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
En værdis tilskrevne type er den type, som en værdi erklæres for at være i overensstemmelse med.
En værdi kan tilskrives en type ved hjælp af biblioteksfunktionen Value.ReplaceType
. Denne funktion returnerer enten en ny værdi med den tilskrevne type eller udløser en fejl, hvis den nye type ikke er kompatibel med værdien.
Når en værdi tilskrives en type, sker der kun en begrænset overensstemmelseskontrol:
- Den type, der tilskrives, skal være ikke-abstrakt, ikke-null og kompatibel med værdiens indbyggede (oprindelige) primitive type.
- Når en brugerdefineret type, der definerer strukturen, tilskrives, skal den matche strukturen af værdien.
- For poster: Typen skal lukkes, skal definere det samme antal felter som værdien og må ikke indeholde valgfrie felter. (Feltnavnene og felttyperne for typen erstatter dem, der i øjeblikket er knyttet til posten. Eksisterende feltværdier kontrolleres dog ikke i forhold til de nye felttyper.)
- For tabeller: Typen skal definere det samme antal kolonner som værdien. (Kolonnenavnene og kolonnetyperne for typen erstatter dem, der i øjeblikket er knyttet til tabellen. Eksisterende kolonneværdier kontrolleres dog ikke i forhold til de nye kolonnetyper.)
- For funktioner: Typen skal definere det samme antal påkrævede parametre samt det samme antal valgfrie parametre som værdien. (Typens parameter og returantagelser samt dens parameternavne erstatter dem, der er knyttet til funktionsværdiens aktuelle type. De nye antagelser har dog ingen indvirkning på funktionens faktiske funktionsmåde.)
- For lister: Værdien skal være en liste. Eksisterende listeelementer kontrolleres dog ikke i forhold til den nye elementtype.
Biblioteksfunktioner kan vælge at beregne og tilskrive komplekse typer til resultater baseret på de tilskrevne typer af inputværdier.
Den tilskrevne type af en værdi kan hentes ved hjælp af biblioteksfunktionen Value.Type
. Eksempler:
Value.Type( Value.ReplaceType( {1}, type {number} )
// type {number}
Typeækvivalens er ikke defineret i M. En M-implementering kan eventuelt vælge at bruge sine egne regler til at udføre lighedssammenligninger mellem typeværdier. Hvis du sammenligner to typeværdier for lighed, skal det evalueres til , hvis de anses for at true
være identiske af implementeringen, og false
ellers. I begge tilfælde skal det returnerede svar være konsistent, hvis de samme to værdier sammenlignes gentagne gange. Bemærk, at hvis du sammenligner nogle identiske typeværdier (f.eks. (type text) = (type text)
) i en given implementering, returneres true
, mens andre (f.eks (type [a = text]) = (type [a = text])
. ) muligvis ikke sammenlignes.
Kompatibilitet mellem en given type og en primitiv type, der kan være null, kan bestemmes ved hjælp af biblioteksfunktionen Type.Is
, som accepterer en vilkårlig typeværdi som den første og en primitiv typeværdi, der kan være null, som det andet 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
Der er ingen understøttelse i M for at bestemme kompatibiliteten af en given type med en brugerdefineret type.
Standardbiblioteket indeholder en samling funktioner, der udtrækker de definerende egenskaber fra en brugerdefineret type, så specifikke kompatibilitetstest kan implementeres som M-udtryk. Nedenfor er nogle eksempler. se specifikationen for M-biblioteket for at få flere oplysninger.
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