Tipos na linguagem de fórmula do Power Query MTypes in the Power Query M formula language

A linguagem de fórmula do Power Query M é uma linguagem de mashup de dados útil e expressiva.The Power Query M Formula Language is a useful and expressive data mashup language. No entanto, ela tem algumas limitações.But it does have some limitations. Por exemplo, não há nenhuma imposição forte do sistema de tipos.For example, there is no strong enforcement of the type system. Em alguns casos, uma validação mais rigorosa é necessária.In some cases, a more rigorous validation is needed. Felizmente, o M fornece uma biblioteca interna compatível com tipos para viabilizar uma validação mais forte.Fortunately, M provides a built-in library with support for types to make stronger validation feasible.

Os desenvolvedores devem ter uma compreensão abrangente do sistema de tipos para que possam fazer isso com qualquer generalidade.Developers should have a thorough understanding of the type system in-order to do this with any generality. E embora a especificação da linguagem do Power Query M explique bem o sistema de tipos, ela ainda deixa algumas surpresas.And, while the Power Query M language specification explains the type system well, it does leave a few surprises. Por exemplo, a validação de instâncias de função requer uma forma de comparar tipos quanto à compatibilidade.For example, validation of function instances requires a way to compare types for compatibility.

Ao explorar o sistema de tipos do M mais cuidadosamente, muitos desses problemas poderão ser esclarecidos e os desenvolvedores se capacitarão a criar as soluções de que precisam.By exploring the M type system more carefully, many of these issues can be clarified, and developers will be empowered to craft the solutions they need.

O conhecimento de cálculo de predicados e a teoria ingênua dos conjuntos devem ser adequados para a compreensão da notação usada.Knowledge of predicate calculus and naïve set theory should be adequate to understand the notation used.

ETAPAS PRELIMINARESPRELIMINARIES

(1) B := { true; false }(1) B := { true; false }
B é o conjunto típico de valores boolianosB is the typical set of Boolean values

(2) N := { identificadores M válidos }(2) N := { valid M identifiers }
N é o conjunto de todos os nomes válidos em M. Isso é definido em outro lugar.N is the set of all valid names in M. This is defined elsewhere.

(3) P := ⟨B, T(3) P := ⟨B, T
P é o conjunto de parâmetros de função. Cada um é possivelmente opcional e tem um tipo. Os nomes de parâmetro são irrelevantes.P is the set of function parameters. Each one is possibly optional, and has a type. Parameter names are irrelevant.

(4) Pn := 0≤i≤ni, Pi(4) Pn := 0≤i≤ni, Pi
Pn é o conjunto de todas as sequências ordenadas de n parâmetros de função.Pn is the set of all ordered sequences of n function parameters.

(5) P* := 0≤i≤∞ Pi(5) P* := 0≤i≤∞ Pi
P* é o conjunto de todas as sequências possíveis de parâmetros de função, em ordem crescente, começando pelas de comprimento 0.P* is the set of all possible sequences of function parameters, from length 0 on up.

(6) F := ⟨B, N, T(6) F := ⟨B, N, T
F é o conjunto de todos os campos de registro. Cada campo é possivelmente opcional, tem um nome e um tipo.F is the set of all record fields. Each field is possibly optional, has a name, and a type.

(7) Fn := 0≤i≤n F(7) Fn := 0≤i≤n F
Fn é o conjunto de todos os campos de registro.Fn is the set of all sets of n record fields.

(8) F* := ( ⋃0≤i≤∞ Fi ) ∖ { F | ⟨b1 , n1 , t1 ⟩, ⟨b2 , n2 , t2 ⟩ ∈ Fn1 = n2 }(8) F* := ( ⋃0≤i≤∞ Fi ) ∖ { F | ⟨b1, n1, t1⟩, ⟨b2, n2, t2⟩ ∈ Fn1 = n2 }
F* é o conjunto de todos os conjuntos (de qualquer tamanho) de campos de registro, exceto pelos conjuntos em que mais de um campo tem o mesmo nome.F* is the set of all sets (of any length) of record fields, except for the sets where more than one field has the same name.

(9) C := ⟨N,T(9) C := ⟨N,T
C é o conjunto de tipos de coluna para tabelas. Cada coluna tem um nome e um tipo.C is the set of column types, for tables. Each column has a name and a type.

(10) Cn0≤i≤ni, C(10) Cn0≤i≤ni, C
Cn é o conjunto de todas as sequências de tipos de coluna n.Cn is the set of all ordered sequences of n column types.

(11) C* := ( ⋃0≤i≤∞ Ci ) ∖ { Cm | ⟨a, ⟨n1 , t1 ⟩⟩, ⟨b, ⟨n2 , t2 ⟩⟩ ∈ Cmn1 = n2 }(11) C* := ( ⋃0≤i≤∞ Ci ) ∖ { Cm | ⟨a, ⟨n1, t1⟩⟩, ⟨b, ⟨n2, t2⟩⟩ ∈ Cmn1 = n2 }
C* é o conjunto de todas as combinações (de qualquer tamanho) de tipos de coluna, exceto aquelas em que mais de uma coluna tem o mesmo nome.C* is the set of all combinations (of any length) of column types, except for those where more than one column has the same name.

TIPOS DE MM TYPES

(12) TF := ⟨P, P*(12) TF := ⟨P, P*
Um tipo de função consiste em um tipo de retorno e uma lista ordenada de zero ou mais parâmetros de função.A Function Type consists of a return type, and an ordered list of zero-or-more function parameters.

(13) TL :=〖T(13) TL :=〖T
Um tipo de lista é indicado por um determinado tipo (chamado de "tipo de item") encapsulado entre chaves. Já que as chaves são usadas na metalinguagem, os colchetes 〖 〗 são usados neste documento.A List type is indicated by a given type (called the "item type") wrapped in curly braces. Since curly braces are used in the metalanguage, 〖 〗 brackets are used in this document.

(14) TR := ⟨B, F*(14) TR := ⟨B, F*
Um tipo de registro tem um sinalizador que indica se ele está "aberto" e tem zero ou mais campos de registro não ordenados.A Record Type has a flag indicating whether it's "open", and zero-or-more unordered record fields.

(15) TRo := ⟨true, F(15) TRo := ⟨true, F

(16) TR := ⟨false, F(16) TR := ⟨false, F
TRo e TR são atalhos de notação para tipos de registro abertos e fechados, respectivamente. TRo and TR are notational shortcuts for open and closed record types, respectively.

(17) TT := C*(17) TT := C*
Um tipo de tabela é uma sequência ordenada de zero ou mais tipos de coluna, em que não há conflitos de nome.A Table Type is an ordered sequence of zero-or-more column types, where there are no name collisions.

(18) TP := { any; none; null; logical; number; time; date; datetime; datetimezone; duration; text; binary; type; list; record; table; function; anynonnull }(18) TP := { any; none; null; logical; number; time; date; datetime; datetimezone; duration; text; binary; type; list; record; table; function; anynonnull }
Um tipo primitivo é um contido nesta lista de palavras-chave do M.A Primitive Type is one from this list of M keywords.

(19) TN := { tn , u ∈ T | tn = u+null } = nullable t(19) TN := { tn, u ∈ T | tn = u+null } = nullable t
Qualquer tipo também pode ser marcado como permitindo valor nulo, usando a palavra-chave "nullable".Any type can additionally be marked as being nullable, by using the "nullable" keyword.

(20) T := TF TL TR TT TP TN(20) T := TF TL TR TT TP TN
O conjunto de todos os tipos do M é a união de todos estes seis conjuntos de tipos: Tipos de função, tipos de lista, tipos de registro, tipos de tabela, tipos primitivos e tipos que permitem valor nulo.The set of all M types is the union of these six sets of types: Function Types, List Types, Record Types, Table Types, Primitive Types, and Nullable Types.

FUNÇÕESFUNCTIONS

É necessário definir uma função: NonNullable : TTOne function needs to be defined: NonNullable : TT
Essa função usa um tipo e retorna um tipo equivalente, exceto pelo fato de que esse segundo tipo não está em conformidade com o valor nulo.This function takes a type, and returns a type that is equivalent except it does not conform with the null value.

IDENTIDADESIDENTITIES

Algumas identidades são necessárias para definir alguns casos especiais e também podem ajudar a elucidar os casos acima.Some identities are needed to define some special cases, and may also help elucidate the above.

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

COMPATIBILIDADE DE TIPOTYPE COMPATIBILITY

Conforme ressaltado em outra parte deste documento, um tipo M será compatível com outro tipo M se e somente se todos os valores que estiverem em conformidade com o primeiro tipo também estiverem em conformidade com o segundo tipo.As defined elsewhere, an M type is compatable with another M type if and only if all values that conform to the first type also conform to the second type.

Temos definida aqui uma relação de compatibilidade que não depende de valores estarem em conformidade e é baseada nas propriedades dos tipos propriamente ditos.Here is defined a compatability relation that does not depend on conforming values, and is based on the properties of the types themselves. Espera-se que essa relação, conforme definido neste documento, seja completamente equivalente à definição semântica original.It is anticiplated that this relation, as defined in this document, is completely equivalent to the original semantic definition.

A relação "é compatível com": ≤ : BT × TThe "is compatible with" relation : ≤ : BT × T
Na seção abaixo, uma letra t minúscula sempre representará um tipo do M, um elemento de T.In the below section, a lowercase t will always represent an M Type, an element of T.

Um Φ representará um subconjunto de F* ou de C*.A Φ will represent a subset of F*, or of C*.

(28) tt(28) tt
Essa relação é reflexiva.This relation is reflexive.

(29) tatbtbtctatc(29) tatbtbtctatc
Essa relação é transitiva.This relation is transitive.

(30) none ≤ t ≤ any(30) none ≤ t ≤ any
Os tipos do M formam uma malha sobre essa relação; none é a parte inferior e any é a parte superior.M types form a lattice over this relation; none is the bottom, and any is the top.

(31) ta , tbTNtataNonNullable(ta ) ≤ NonNullable(tb )(31) ta, tbTNtataNonNullable(ta) ≤ NonNullable(tb)
Se dois tipos forem compatíveis, os equivalentes NonNullable também serão compatíveis.If two types are compatible, then the NonNullable equivalents are also compatible.

(32) null ≤ tTN(32) null ≤ tTN
O tipo primitivo null é compatível com todos os tipos que permitem valor nulo.The primitive type null is compatible with all nullable types.

(33) tTN ≤ anynonnull(33) tTN ≤ anynonnull
Todos os tipos NonNullable são compatíveis com anynonnull.All nonnullable types are compatible with anynonnull.

(34) NonNullable(t) ≤ t(34) NonNullable(t) ≤ t
Um tipo NonNullable é compatível com o equivalente anulável.A NonNullible type is compatible with the nullable equivalent.

(35) tTFt ≤ function(35) tTFt ≤ function
Todos os tipos de função são compatíveis com function.All function types are compatible with function.

(36) tTLt ≤ list(36) tTLt ≤ list
Todos os tipos de lista são compatíveis com list.All list types are compatible with list.

(37) tTRt ≤ record(37) tTRt ≤ record
Todos os tipos de registro são compatíveis com record.All record types are compatible with record.

(38) tTTt ≤ table(38) tTTt ≤ table
Todos os tipos de tabela são compatíveis com table.All table types are compatible with table.

(39) tatb ↔ 〖ta 〗≤〖tb(39) tatb ↔ 〖ta〗≤〖tb
Um tipo de lista será compatível com outro tipo de lista se os tipos de item forem compatíveis e vice-versa.A list type is compaible with another list type if the item types are compatible, and vice-versa.

(40) taTF = ⟨ pa , p* ⟩, tbTF = ⟨ pb , p* ⟩ ∧ papbtatb(40) taTF = ⟨ pa, p* ⟩, tbTF = ⟨ pb, p* ⟩ ∧ papbtatb
Um tipo de função será compatível com outro tipo de função se os tipos de retorno forem compatíveis e as listas de parâmetros forem idênticas.A function type is compatible with another function type if the return types are compatible, and the parameter lists are identical.

(41) taTRo, tbTRtatb(41) taTRo, tbTRtatb
Um tipo de registro aberto nunca é compatível com um tipo de registro fechado.An open record type is never compatible with a closed record type.

(42) taTR = ⟨false, Φ ⟩, tbTRo = ⟨true, Φ ⟩ → tatb(42) taTR = ⟨false, Φ⟩, tbTRo = ⟨true, Φ⟩ → tatb
Um tipo de registro fechado é compatível com outro tipo de registro quase idêntico, exceto por ser aberto.A closed record type is compatible with an otherwise identical open record type.

(43) taTRo = ⟨true, ( Φ , ⟨true, n, any⟩)⟩, tbTRo = ⟨true, Φ ⟩ → tatbtbta(43) taTRo = ⟨true, (Φ, ⟨true, n, any⟩)⟩, tbTRo = ⟨true, Φ⟩ → tatbtbta
Um campo opcional com o tipo any pode ser ignorado ao comparar dois tipos de registros abertos.An optional field with the type any may be ignored when comparing two open record types.

(44) taTR = ⟨b, (Φ, ⟨β, n, ua⟩)⟩, tbTR = ⟨b, (Φ, ⟨β, n, ub⟩)⟩ ∧ uaubtatb(44) taTR = ⟨b, (Φ, ⟨β, n, ua⟩)⟩, tbTR = ⟨b, (Φ, ⟨β, n, ub⟩)⟩ ∧ uaubtatb
Dois tipos de registro que diferem somente por um campo serão compatíveis se o nome e a opcionalidade do campo forem idênticos e os tipos desse campo forem compatíveis.Two record types that differ only by one field are compatible if the name and optionality of the field are identical, and the types of said field are compatible.

(45) taTR = ⟨b, (Φ, ⟨false, n, u⟩)⟩, tbTR = ⟨b, (Φ, ⟨true, n, u⟩)⟩ → tatb(45) taTR = ⟨b, (Φ, ⟨false, n, u⟩)⟩, tbTR = ⟨b, (Φ, ⟨true, n, u⟩)⟩ → tatb
Um tipo de registro com um campo não opcional é compatível com um tipo de registro quase idêntico, exceto por ter esse campo como opcional.A record type with a non-optional field is compatible with a record type identical but for that field being optional.

(46) taTRo = ⟨true, ( Φ , ⟨b, n, u⟩)⟩, tbTRo = ⟨true, Φ ⟩ → tatb(46) taTRo = ⟨true, (Φ, ⟨b, n, u⟩)⟩, tbTRo = ⟨true, Φ⟩ → tatb
Um tipo de registro aberto é compatível com outro tipo de registro aberto que tem um campo a menos.An open record type is compatible with another open record type with one fewer field.

(47) taTT = ( Φ , ⟨i, ⟨n, ua ⟩⟩), tbTT = ( Φ , ⟨i, ⟨n, ub ⟩⟩) ∧ uaubtatb(47) taTT = (Φ, ⟨i, ⟨n, ua⟩⟩), tbTT = (Φ, ⟨i, ⟨n, ub⟩⟩) ∧ uaubtatb
Um tipo de tabela é compatível com um segundo tipo de tabela quase idêntico, exceto por ter uma coluna com um tipo diferente, quando os tipos dessa coluna são compatíveis.A table type is compatible with a second table type, which is identical but for one column having a differing type, when the types for that column are compatible.

REFERENCESREFERENCES

Microsoft Corporation (agosto de 2015)Microsoft Corporation (2015 August)
Especificação de linguagem de fórmula do Microsoft Power Query para Excel [PDF]Microsoft Power Query for Excel Formula Language Specification [PDF]
Recuperado de https://msdn.microsoft.com/library/mt807488.aspxRetrieved from https://msdn.microsoft.com/library/mt807488.aspx

Microsoft Corporation. (n. d.)Microsoft Corporation (n.d.)
Referência de função do Power Query M [página da Web]Power Query M function reference [web page]
Recuperado de https://msdn.microsoft.com/library/mt779182.aspxRetrieved from https://msdn.microsoft.com/library/mt779182.aspx