Delen via


Typen in de Power Query M-formuletaal

De Power Query M-formuletaal is een handige en expressieve data mashup-taal. Maar het heeft wel enkele beperkingen. Er is bijvoorbeeld geen sterke afdwinging van het typesysteem. In sommige gevallen is een strengere validatie nodig. Gelukkig biedt M een ingebouwde bibliotheek met ondersteuning voor typen om sterkere validatie mogelijk te maken.

Ontwikkelaars moeten beschikken over een grondig begrip van het type systeem om dit te doen met enige algemeenheid. En terwijl de Power Query M-taalspecificatie het type systeem goed uitlegt, laat het een paar verrassingen achter. Validatie van functie-exemplaren vereist bijvoorbeeld een manier om typen voor compatibiliteit te vergelijken.

Door het M-typesysteem zorgvuldiger te verkennen, kunnen veel van deze problemen worden verduidelijkt en kunnen ontwikkelaars de oplossingen maken die ze nodig hebben.

Kennis van predicaat calculus en naïeve settheorie moet voldoende zijn om inzicht te krijgen in de gebruikte notatie.

PRELIMINARIES

(1) B := { true; false }
B is de typische set Booleaanse waarden

(2) N := { geldige M-id's }
N is de set met alle geldige namen in M. Dit wordt elders gedefinieerd.

(3) P := ⟨B, T
P is de set functieparameters. Elke is mogelijk optioneel en heeft een type. Parameternamen zijn niet relevant.

(4) Pn := ⋃0≤i≤ni, Pi⟩
Pn is de set van alle geordende reeksen van n functieparameters.

(5) P := ⋃0≤i≤∞P i*
P* is de set van alle mogelijke reeksen functieparameters, van lengte 0 op.

(6) F := ⟨B, N, T
F is de set van alle recordvelden. Elk veld is mogelijk optioneel, heeft een naam en een type.

(7) Fn := ∏0≤i≤n F
Fn is de set van alle recordsets van n recordvelden.

(8) F := ( ⋃0≤i≤∞Fi ) ∖ { F | ⟨b1, n 1, t1⟩, ⟨b2, n2, t2⟩ ∈ Fn1 = n2 }*
F* is de set van alle sets (van elke lengte) van recordvelden, met uitzondering van de sets waarbij meer dan één veld dezelfde naam heeft.

(9) C := ⟨N,T
C is de set kolomtypen voor tabellen. Elke kolom heeft een naam en een type.

(10) Cn ⊂ ⋃0≤i≤ni, C⟩
Cn is de set van alle geordende reeksen van n kolomtypen.

(11) C* := ( ⋃0≤i≤∞Ci ) ∖ { Cm | ⟨a, ⟨n1, t1⟩⟩, ⟨b, ⟨n2, t2⟩⟩ ∈ Cm ⋀ n 1 = n2 }
C* is de set van alle combinaties (van elke lengte) van kolomtypen, met uitzondering van de combinaties waarbij meer dan één kolom dezelfde naam heeft.

M TYPES

(12) TF := ⟨P, P⟩*
Een functietype bestaat uit een retourtype en een geordende lijst met nul- of meer functieparameters.

(13) TL :=〖T〗
Een lijsttype wordt aangegeven door een bepaald type (het 'itemtype' genoemd) dat is verpakt in accolades. Aangezien accolades worden gebruikt in de metalanguage, 〖 〗 vierkante haken worden in dit document gebruikt.

(14) TR := ⟨B, F⟩*
Een recordtype heeft een vlag die aangeeft of het 'open' is en dat er geen of meer niet-geordende recordvelden zijn.

(15) TRo := ⟨true, F⟩

(16) TR := ⟨false, F⟩
TRo en TR zijn respectievelijk notatiesneltoetsen voor geopende en gesloten recordtypen.

(17) T:= C *
Een tabeltype is een geordende reeks kolomtypen met nul of meer, waarbij er geen naamconflicten zijn.

(18) TP := { any; none; none; logical; number; time; datetime; datetimezone; duration; text; binary; type; record; table; function; anynonnull }
Een primitief type is een van deze lijst met M-trefwoorden.

(19) TN := { tn, u ∈ T | tn = u+null } = nullable t
Elk type kan ook worden gemarkeerd als nullable, met behulp van het trefwoord 'nullable' .

(20) T := T F ∪ TLTRTTTPT N
De set van alle M-typen is de samenvoeging van deze zes sets typen:
Functietypen, lijsttypen, recordtypen, tabeltypen, primitieve typen en null-typen.

FUNCTIES

Er moet één functie worden gedefinieerd: Niet-inulleerbaar : TT
Deze functie gebruikt een type en retourneert een type dat gelijkwaardig is, behalve dat deze niet voldoet aan de null-waarde.

IDENTITEITEN

Sommige identiteiten zijn nodig om bepaalde speciale gevallen te definiëren en kunnen ook helpen bij het vaststellen van het bovenstaande.

(21) nullable any = any
(22) nullable anynonnull = any
(23) nullable null = null
(24) nullable none = null
(25) nullable nullable tT = nullable t
(26) NonNullable(nullable tT) = NonNullable(t)
(27) NonNullable(any) = anynonnull

TYPECOMPATIBILITEIT

Zoals elders gedefinieerd, is een M-type compatibel met een ander M-type als en alleen als alle waarden die aan het eerste type voldoen, ook voldoen aan het tweede type.

Hier wordt een compatibiliteitsrelatie gedefinieerd die niet afhankelijk is van het voldoen aan waarden en is gebaseerd op de eigenschappen van de typen zelf. Naar verwachting is deze relatie, zoals gedefinieerd in dit document, volledig gelijk aan de oorspronkelijke semantische definitie.

De "is compatibel met" relatie: ≤ : B ← T × T
In de onderstaande sectie vertegenwoordigt een kleine letter t altijd een M-type, een element van T.

Een Φ vertegenwoordigt een subset van F* of C*.

(28) tt
Deze relatie is reflexief.

(29) tatbtbtctat c
Deze relatie is transitief.

(30) geen ≤ geen
M-typen vormen een rooster over deze relatie; geen is de onderkant en een is de bovenkant.

(31) t a, tbTNtataNonNullable(t) ≤ NonNullable(t b)
Als twee typen compatibel zijn, zijn de niet-in aanmerkingbare equivalenten ook compatibel.

(32) null-≤ tT N
Het primitieve type null is compatibel met alle null-typen.

(33) tTN ≤ anynonnull
Alle niet-ullbare typen zijn compatibel met anynonnull.

(34) Niet-≤ t
Een NietNullible-type is compatibel met het equivalent dat null kan worden gebruikt.

(35) t ∈ T Ft ≤, functie
Alle functietypen zijn compatibel met functie.

(36) tTLt ≤ lijst
Alle lijsttypen zijn compatibel met de lijst.

(37) t ∈TRt ≤ record
Alle recordtypen zijn compatibel met records.

(38) t ∈ T Tt ≤ tabel
Alle tabeltypen zijn compatibel met de tabel.

(39) tat b ↔ta〗≤〖t b〗
Een lijsttype is compatibel met een ander lijsttype als de itemtypen compatibel zijn en vice versa.

(40) taTF = ⟨ pa, p* ⟩, tb ∈ TF = ⟨ pb, p* ⟩ ∧ pa ≤ p btatb b
Een functietype is compatibel met een ander functietype als de retourtypen compatibel zijn en de parameterlijsten identiek zijn.

(41) taTRo, tbTR• → t at b
Een geopend recordtype is nooit compatibel met een gesloten recordtype.

(42) taTR• = ⟨false, Φ⟩, tbTRo = ⟨true, Φ⟩ → t at b
Een gesloten recordtype is compatibel met een anderszins identiek open recordtype.

(43) taTRo = ⟨true, (Φ, ⟨true, n, any⟩)⟩, t bT Ro = ⟨true, Φ⟩ → tatbt b ≤ ta a
Een optioneel veld met het type kan worden genegeerd bij het vergelijken van twee geopende recordtypen.

(44) taT R = ⟨b, (Φ, ⟨β, n, ua⟩)⟩, tb ∈ T R = ⟨b, (Φ, ⟨β, n, ub⟩)⟩ ∧ ueenub → t at b
Twee recordtypen die slechts met één veld verschillen, zijn compatibel als de naam en optioneelheid van het veld identiek zijn en de typen van dit veld compatibel zijn.

(45) taTR = ⟨b, (Φ, ⟨false, n, u⟩)⟩, tbT R = ⟨b, (Φ, ⟨true, n, u⟩)⟩ → tatb b
Een recordtype met een niet-optioneel veld is compatibel met een recordtype identiek, maar voor dat veld is optioneel.

(46) taTRo = ⟨true, (Φ, ⟨b, n, u⟩)⟩, tbT Ro = ⟨true, Φ⟩ → t at b
Een geopend recordtype is compatibel met een ander open recordtype met één kleiner veld.

(47) taT = (Φ, ⟨i, ⟨n, ua⟩⟩), tbT = (Φ, ⟨i, ⟨n, ub⟩⟩) ∧ uaub → t atb b
Een tabeltype is compatibel met een tweede tabeltype, dat identiek is, maar voor één kolom met een verschillend type, wanneer de typen voor die kolom compatibel zijn.

REFERENTIES

Microsoft Corporation (2015 augustus)
Microsoft Power Query voor Excel-formuletaalspecificatie [PDF]
Teruggeplaatst https://msdn.microsoft.com/library/mt807488.aspx

Microsoft Corporation (n.d.)
Naslaginformatie over de Power Query M-functie [webpagina]
Teruggeplaatst https://msdn.microsoft.com/library/mt779182.aspx