Share via


Typen

Een typewaarde is een waarde die andere waarden classificeert . Een waarde die door een type wordt geclassificeerd, wordt gezegd dat deze voldoet aan dat type. Het M-typesysteem bestaat uit de volgende typen:

  • Primitieve typen, die primitieve waarden classificeren (binary, date, datetime, datetimezone, duration, , , nulllogicalrecordnumberlisttext, time, ) typeen ook een aantal abstracte typen (function, table, anyen ) anynonnullnone

  • Recordtypen, waarmee recordwaarden worden geclassificeerd op basis van veldnamen en waardetypen

  • Lijsttypen, waarmee lijsten worden geclassificeerd met één itembasistype

  • Functietypen, waarmee functiewaarden worden geclassificeerd op basis van de typen van hun parameters en retourwaarden

  • Tabeltypen, waarmee tabelwaarden worden geclassificeerd op basis van kolomnamen, kolomtypen en sleutels

  • Null-typen, waarmee de waarde null wordt geclassificeerd naast alle waarden die zijn geclassificeerd door een basistype

  • Typetypen, waarmee waarden worden geclassificeerd die typen zijn

De set primitieve typen omvat de typen primitieve waarden en een aantal abstracte typen, die typen zijn die geen unieke classificatie van waarden hebben: function, table, anyen anynonnullnone. Alle functiewaarden voldoen aan het abstracte type function, alle tabelwaarden aan het abstracte type table, alle waarden aan het abstracte type any, alle niet-null-waarden voor het abstracte type anynonnullen geen waarden voor het abstracte type none. Een expressie van het type none moet een fout veroorzaken of niet beëindigen omdat er geen waarde kan worden geproduceerd die voldoet aan het type none. Houd er rekening mee dat de primitieve typen function en table abstract zijn omdat er geen functie of tabel rechtstreeks van deze typen is. De primitieve typen record en list zijn niet-abstract omdat ze een geopende record vertegenwoordigen zonder gedefinieerde velden en een lijst met elk type.

Alle typen die geen lid zijn van de gesloten set primitieve typen plus hun nullable tegenhangers worden gezamenlijk aangepaste typen genoemd. Aangepaste typen kunnen worden geschreven met behulp van:type-expression

type-expressie:
      primaire expressie

      typeprimair type
type:
      primaire expressie
      primair type
primair type:
      primitief-type
      recordtype
      list-type
      functietype
      tabeltype
      nullable-type
primitieve-type:
een van
      any anynonnull binary date datetime datetimezone duration function list logical
      none null number record table text time type

De primitieve namen zijn contextuele trefwoorden die alleen worden herkend in een typecontext . Het gebruik van haakjes in een typecontext verplaatst de grammatica terug naar een reguliere expressiecontext, waarbij het gebruik van het trefwoord van het type moet worden teruggezet naar een typecontext. Als u bijvoorbeeld een functie wilt aanroepen in een typecontext , kunnen haakjes worden gebruikt:

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

Haakjes kunnen ook worden gebruikt voor toegang tot een variabele waarvan de naam botst met een primitieve-typenaam :

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

In het volgende voorbeeld wordt een type gedefinieerd dat een lijst met getallen classificeert:

type { number }

Op dezelfde manier definieert het volgende voorbeeld een aangepast type dat records classificeert met verplichte velden met de naam X en Y waarvan de waarden getallen zijn:

type [ X = number, Y = number ]

Het getypte type van een waarde wordt verkregen met behulp van de standaardbibliotheekfunctie Value.Type, zoals wordt weergegeven in de volgende voorbeelden:

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

De is operator wordt gebruikt om te bepalen of het type van een waarde compatibel is met een bepaald type, zoals wordt weergegeven in de volgende voorbeelden:

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

De as operator controleert of de waarde compatibel is met het opgegeven type en genereert een fout als dat niet het is. Anders wordt de oorspronkelijke waarde geretourneerd.

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

Houd er rekening mee dat de is operators as alleen nullable primitieve typen accepteren als de juiste operand. M biedt geen middelen om waarden te controleren op overeenstemming met aangepaste typen.

Een type X is compatibel met een type Y als en alleen als alle waarden die voldoen X aan ook voldoen.Y Alle typen zijn compatibel met type any en geen typen (maar none zelf) zijn compatibel met het type none. In de volgende grafiek ziet u de compatibiliteitsrelatie. (Typecompatibiliteit is reflexief en transitief. Het vormt een lattice met type any als de bovenkant en het type none als de laagste waarde.) De namen van abstracte typen worden cursief ingesteld.

Typecompatibiliteit

De volgende operators worden gedefinieerd voor typewaarden:

Operator Resultaat
x = y Equal
x <> y Not equal
x ?? y Coalesce

Het systeemeigen type van typewaarden is het intrinsieke type type.

Primitieve typen

Typen in de M-taal vormen een niet-aaneengesloten hiërarchie die is geroot op type any. Dit is het type dat alle waarden classificeert. Elke M-waarde voldoet aan precies één primitief subtype van any. De gesloten set primitieve typen die zijn afgeleid van het type any zijn als volgt:

  • type null, waarmee de null-waarde wordt classificeerd.
  • type logical, waarmee de waarden waar en onwaar worden geclassificeerd.
  • type number, waarmee getalwaarden worden geclassificeerd.
  • type time, waarmee tijdwaarden worden geclassificeerd.
  • type date, waarmee datumwaarden worden geclassificeerd.
  • type datetime, waarmee datum/tijd-waarden worden geclassificeerd.
  • type datetimezone, waarmee datum/tijdzone-waarden worden geclassificeerd.
  • type duration, waarmee duurwaarden worden geclassificeerd.
  • type text, waarmee tekstwaarden worden geclassificeerd.
  • type binary, waarmee binaire waarden worden geclassificeerd.
  • type type, waarmee typewaarden worden geclassificeerd.
  • type list, waarmee lijstwaarden worden geclassificeerd.
  • type record, waarmee recordwaarden worden geclassificeerd.
  • type table, waarmee tabelwaarden worden geclassificeerd.
  • type function, waarmee functiewaarden worden geclassificeerd.
  • type anynonnull, waarmee alle waarden worden geclassificeerd, met uitzondering van null.
  • type none, waarmee geen waarden worden geclassificeerd.

Elk type

Het type any is abstract, classificeert alle waarden in M en alle typen in M zijn compatibel met any. Variabelen van het type any kunnen worden gebonden aan alle mogelijke waarden. Aangezien any abstract is, kan het niet worden toegeschreven aan waarden, dat wil gezegd, geen waarde rechtstreeks van het type anyis.

Lijsttypen

Elke waarde die een lijst is, voldoet aan het intrinsieke type list, waardoor geen beperkingen gelden voor de items binnen een lijstwaarde.

list-type:
      {itemtype}
itemtype:
      Type

Het resultaat van het evalueren van een lijsttype is een lijsttypewaarde waarvan het basistype is list.

In de volgende voorbeelden ziet u de syntaxis voor het declareren van homogene lijsttypen:

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

Een waarde voldoet aan een lijsttype als de waarde een lijst is en elk item in die lijstwaarde voldoet aan het itemtype van het lijsttype.

Het itemtype van een lijsttype geeft een afhankelijkheid aan: alle items van een conforme lijst voldoen aan het itemtype.

Recordtypen

Elke waarde die een record is, voldoet aan de intrinsieke typerecord, waardoor geen beperkingen gelden voor de veldnamen of -waarden binnen een recordwaarde. Een recordtypewaarde wordt gebruikt om de set geldige namen en de typen waarden te beperken die aan deze namen mogen worden gekoppeld.

recordtype:
      [open-record-marker]
      [opt voor field-specification-list]
      [field-specification-list , open-record-marker]
field-specification-list:
      veldspecificatie
      field-specification,field-specification-list
veldspecificatie:

      optional opt field-name field-type-specificationopt
veldtypespecificatie:

      =veldtype
veldtype:
      type
open-recordmarkering:

      ...

Het resultaat van het evalueren van een recordtype is een typewaarde waarvan het basistype is record.

In de volgende voorbeelden ziet u de syntaxis voor het declareren van recordtypen:

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

Recordtypen worden standaard gesloten , wat betekent dat extra velden die niet aanwezig zijn in de veldspecificatielijst , niet mogen aanwezig zijn in het voldoen aan waarden. Als u de openrecordmarkering in het recordtype opneemt, wordt opgegeven dat het type geopend is, waardoor velden die niet aanwezig zijn in de lijst met veldspecificaties, zijn toe te staan. De volgende twee expressies zijn equivalent:

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

Een waarde voldoet aan een recordtype als de waarde een record is en elke veldspecificatie in het recordtype is voldaan. Aan een veldspecificatie wordt voldaan als een van de volgende waar is:

  • Er bestaat een veldnaam die overeenkomt met de id van de specificatie in de record en de bijbehorende waarde voldoet aan het type van de specificatie

  • De specificatie is gemarkeerd als optioneel en er wordt geen overeenkomende veldnaam gevonden in de record

Een conforme waarde kan veldnamen bevatten die niet worden vermeld in de lijst met veldspecificaties als en alleen als het recordtype is geopend.

Functietypen

Elke functiewaarde voldoet aan het primitieve type function, waarbij geen beperkingen worden ingesteld voor de typen formele parameters van de functie of de retourwaarde van de functie. Een aangepaste functietypewaarde wordt gebruikt om typebeperkingen te plaatsen voor de handtekeningen van conforme functiewaarden.

functietype:
      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:
      parameterspecificatie
optional-parameter-specification-list:
      optioneel-parameterspecificatie
      optional-parameter-specification optional-parameter-specification-list
,
optional-parameter-specification:

      optionalparameterspecificatie
parameterspecificatie:
      parameter-naam parameter-type
function-return-type:
      assertion
Bewering:

      asnullable-primitive-type

Het resultaat van het evalueren van een functietype is een typewaarde waarvan het basistype is function.

In de volgende voorbeelden ziet u de syntaxis voor het declareren van functietypen:

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

Een functiewaarde voldoet aan een functietype als het retourtype van de functiewaarde compatibel is met het retourtype van het functietype en elke parameterspecificatie van het functietype compatibel is met de positioneel overeenkomende formele parameter van de functie. Een parameterspecificatie is compatibel met een formele parameter als het opgegeven parametertype compatibel is met het type van de formele parameter en de parameterspecificatie is optioneel als de formele parameter optioneel is.

Formele parameternamen worden genegeerd voor het bepalen van de conformiteit van het functietype.

Als u een parameter opgeeft als optioneel, kan het type impliciet null worden. De volgende typen identieke functies maken:

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

Tabeltypen

Een tabeltypewaarde wordt gebruikt om de structuur van een tabelwaarde te definiëren.

tabeltype:
      tablerijtype
rijtype:

      [opt voor field-specification-list]

Het resultaat van het evalueren van een tabeltype is een typewaarde waarvan het basistype is table.

Het rijtype van een tabel geeft de kolomnamen en kolomtypen van de tabel op als een gesloten recordtype. Zodat alle tabelwaarden voldoen aan het type table, is het rijtype van record het type (het lege geopende recordtype). Het type tabel is dus abstract omdat geen tabelwaarde het rijtype van het type kan hebben table(maar alle tabelwaarden hebben een rijtype dat compatibel is met het rijtype van het type table). In het volgende voorbeeld ziet u de constructie van een 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

Een tabeltypewaarde bevat ook de definitie van de sleutels van een tabelwaarde. Een sleutel is een set kolomnamen. Maximaal één sleutel kan worden aangewezen als de primaire sleutel van de tabel. (In M hebben tabelsleutels geen semantische betekenis. Het is echter gebruikelijk dat externe gegevensbronnen, zoals databases of OData-feeds, sleutels over tabellen definiëren. Power Query gebruikt belangrijke informatie om de prestaties van geavanceerde functionaliteit te verbeteren, zoals joinbewerkingen tussen meerdere bronnen.)

De standaardbibliotheekfuncties Type.TableKeysen Type.AddTableKeyType.ReplaceTableKeys kunnen worden gebruikt om de sleutels van een tabeltype te verkrijgen, een sleutel toe te voegen aan een tabeltype en alle sleutels van een tabeltype te vervangen.

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-typen

Voor elke type T, kan een nullable variant worden afgeleid met behulp van nullable-type:

nullable-type:
      nullabletype

Het resultaat is een abstract type dat waarden van het type T of de waarde nulltoestaat.

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

Ascriptie van type nullableT vermindert tot beschrijving van type null of typeT. (Zoals u weet, zijn null-typen abstract en kan er geen waarde rechtstreeks van abstract type zijn.)

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

De standaardbibliotheekfuncties Type.IsNullable en Type.NonNullable kunnen worden gebruikt om een type te testen op nullbaarheid en om null-functionaliteit van een type te verwijderen.

De volgende bewaring (voor elke type T):

  • type T is compatibel met type nullable T
  • Type.NonNullable(type T) is compatibel met type T

Hier volgen paarsgewijze equivalenten (voor elke):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

Getscribeerd type van een waarde

Het getscribeerde type van een waarde is het type waaraan een waarde wordt gedeclareerd om te voldoen.

Een waarde kan een type worden toegekend met behulp van de bibliotheekfunctie Value.ReplaceType. Deze functie retourneert een nieuwe waarde met het type dat is toegekend of genereert een fout als het nieuwe type niet compatibel is met de waarde.

Wanneer een waarde wordt toegekend aan een type, vindt er slechts een beperkte nalevingscontrole plaats:

  • Het type dat wordt toegekend, moet niet-abstract, niet nullable zijn en compatibel zijn met het intrinsieke (systeemeigen) primitieve type van de waarde.
  • Wanneer een aangepast type dat structuur definieert, moet deze overeenkomen met de structuur van de waarde.
    • Voor records: het type moet worden gesloten, moet hetzelfde aantal velden definiëren als de waarde en mag geen optionele velden bevatten. (De veldnamen en veldtypen van het type vervangen die momenteel aan de record zijn gekoppeld. Bestaande veldwaarden worden echter niet gecontroleerd op basis van de nieuwe veldtypen.)
    • Voor tabellen: Het type moet hetzelfde aantal kolommen definiëren als de waarde. (De kolomnamen en kolomtypen van het type vervangen de kolomtypen die momenteel aan de tabel zijn gekoppeld. Bestaande kolomwaarden worden echter niet gecontroleerd op basis van de nieuwe kolomtypen.)
    • Voor functies: Het type moet hetzelfde aantal vereiste parameters definiëren, evenals hetzelfde aantal optionele parameters als de waarde. (De parameter van het type en retourneert asserties, evenals de parameternamen, vervangen die zijn gekoppeld aan het huidige type van de functiewaarde. De nieuwe asserties hebben echter geen effect op het werkelijke gedrag van de functie.)
    • Voor lijsten: De waarde moet een lijst zijn. (Bestaande lijstitems worden echter niet gecontroleerd op het nieuwe itemtype.)

Bibliotheekfuncties kunnen ervoor kiezen om complexe typen te berekenen en toe te schrijven aan resultaten op basis van de getscribeerde typen van de invoerwaarden.

Het toegeschreven type van een waarde kan worden verkregen met behulp van de bibliotheekfunctie Value.Type. Voorbeeld:

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

Gelijkwaardigheid en compatibiliteit van type

De gelijkwaardigheid van het type is niet gedefinieerd in M. Een M-implementatie kan er eventueel voor kiezen om eigen regels te gebruiken om gelijkheidsvergelijkingen tussen typewaarden uit te voeren. Als u twee typewaarden voor gelijkheid vergelijkt, moet worden geëvalueerd true of deze identiek worden geacht door de implementatie en false anders. In beide gevallen moet het geretourneerde antwoord consistent zijn als dezelfde twee waarden herhaaldelijk worden vergeleken. Houd er rekening mee dat het vergelijken van een aantal identieke typewaarden (zoals (type text) = (type text)) binnen een bepaalde implementatie mogelijk niet retourneert true, terwijl andere (zoals (type [a = text]) = (type [a = text])) niet worden vergeleken.

Compatibiliteit tussen een bepaald type en een primitief type dat null kan worden gebruikt, kan worden bepaald met behulp van de bibliotheekfunctie Type.Is, die een willekeurige typewaarde accepteert als eerste en een nullable primitieve typewaarde als het tweede 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

Er is geen ondersteuning in M voor het bepalen van de compatibiliteit van een bepaald type met een aangepast type.

De standaardbibliotheek bevat een verzameling functies om de definiërende kenmerken van een aangepast type te extraheren, zodat specifieke compatibiliteitstests kunnen worden geïmplementeerd als M-expressies. Hieronder ziet u enkele voorbeelden; raadpleeg de M-bibliotheekspecificatie voor volledige details.

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