Partilhar via


Comportamento do operador

Esta seção define o comportamento dos vários operadores M.

Precedência dos operadores

Quando uma expressão contém vários operadores, a precedência dos operadores controla a ordem na qual os operadores individuais são avaliados. Por exemplo, a expressão x + y * z é avaliada como x + (y * z) porque o * operador tem maior precedência do que o operador binário + . A precedência de um operador é estabelecida pela definição da sua produção gramatical associada. Por exemplo, uma expressão aditiva consiste em uma sequência de expressões multiplicativas separadas por + ou - operadores, dando assim aos + operadores e - menor precedência do que os * operadores e / .

A produção de expressão entre parênteses pode ser usada para alterar a ordem de precedência padrão.

expressão entre parênteses:
       ( expressão)

Por exemplo:

1 + 2 * 3       // 7 
(1 + 2) * 3     // 9

A tabela a seguir resume os operadores M, listando as categorias de operadores em ordem de precedência do mais alto para o mais baixo. Os operadores da mesma categoria têm igual precedência.

Categoria Expression Description
Primário eu
@ eu
Expressão do identificador
x) Expressão entre parênteses
x[i] Procura
x{y} Acesso ao item
x(...) Invocação de função
{x, y, ...} Inicialização da lista
[ i = x, ... ] Inicialização de registros
... Não implementado
Unário + x Identidade
- x Negação
not x Negação lógica
Metadados xmetay Associar metadados
Multiplicativo x * y Multiplicação
x / y Divisão
Aditivo x + y Adição
x - y Subtração
Relacional x< y Menor que
x > y Maior que
x<= y Menor ou igual a
x >= y Maior ou igual a
Equality x = y Igual
x<> y Não é igual a
Asserção de tipo xasy É compatível tipo primitivo nulo ou erro
Conformidade com o tipo xisy Teste se o tipo de primitiva nula compatível
Lógica E xandy Conjunção de curto-circuito
Lógica OU xory Disjunção de curto-circuito
Coalesce x??y Operador coalescente nulo

Operadores e metadados

Cada valor tem um valor de registro associado que pode conter informações adicionais sobre o valor. Esse registro é conhecido como o registro de metadados para um valor. Um registro de metadados pode ser associado a qualquer tipo de valor, até mesmo null. O resultado dessa associação é um novo valor com os metadados fornecidos.

Um registro de metadados é apenas um registro regular e pode conter quaisquer campos e valores que um registro regular pode, e ele próprio tem um registro de metadados. Associar um registro de metadados a um valor é "não intrusivo". Ele não altera o comportamento do valor em avaliações, exceto aquelas que inspecionam explicitamente os registros de metadados.

Cada valor tem um registro de metadados padrão, mesmo que um não tenha sido especificado. O registro de metadados padrão está vazio. Os exemplos a seguir mostram o acesso ao registro de metadados de um valor de texto usando a Value.Metadata função de biblioteca padrão:

Value.Metadata( "Mozart" )   // []

Os registros de metadados geralmente não são preservados quando um valor é usado com um operador ou função que constrói um novo valor. Por exemplo, se dois valores de texto forem concatenados usando o & operador, os metadados do valor de texto resultante serão o registro []vazio. As seguintes expressões são equivalentes:

"Amadeus " & ("Mozart" meta [ Rating = 5 ])  
"Amadeus " & "Mozart"

A biblioteca padrão funciona Value.RemoveMetadata e Value.ReplaceMetadata pode ser usada para remover todos os metadados de um valor e substituir os metadados de um valor (em vez de mesclar metadados em metadados possivelmente existentes).

O único operador que retorna resultados que carregam metadados é o operador meta.

Operadores estruturalmente recursivos

Os valores podem ser cíclicos. Por exemplo:

let l = {0, @l} in l
// {0, {0, {0, ... }}}
[A={B}, B={A}]
// [A = {{ ... }}, B = {{ ... }}]

M lida com valores cíclicos mantendo a construção de registros, listas e tabelas preguiçosa. Uma tentativa de construir um valor cíclico que não se beneficia de valores estruturados preguiçosos interjeitados produz um erro:

[A=B, B=A] 
// [A = Error.Record("Expression.Error", 
//         "A cyclic reference was encountered during evaluation"), 
//  B = Error.Record("Expression.Error", 
//         "A cyclic reference was encountered during evaluation"), 
// ]

Alguns operadores em M são definidos por recursão estrutural. Por exemplo, a igualdade de registros e listas é definida pela igualdade conjugada de campos de registro e listas de itens correspondentes, respectivamente.

Para valores não cíclicos, a aplicação da recursão estrutural produz uma expansão finita do valor: valores aninhados compartilhados serão percorridos repetidamente, mas o processo de recursão sempre termina.

Um valor cíclico tem uma expansão infinita ao aplicar a recursão estrutural. A semântica de M não faz nenhuma acomodação especial para tais expansões infinitas – uma tentativa de comparar valores cíclicos para igualdade, por exemplo, normalmente ficará sem recursos e terminará excepcionalmente.

Operadores de Seleção e Projeção

Os operadores de seleção e projeção permitem extrair dados de valores de lista e registro.

Acesso ao Item

Um valor pode ser selecionado de uma lista ou tabela com base em sua posição baseada em zero dentro dessa lista ou tabela usando uma expressão de acesso ao item.

item-access-expression:
      seleção de itens
      opcional-item-seleção
seleção de itens:
      seletor de item de expressão
{primária}
opcional-item-seleção:
      seletor de item de expressão
{primária} ?
seletor de itens:
      expressão

A expressão item-access-retornax{y}:

  • Para uma lista x e um número y, o item da lista x na posição y. Considera-se que o primeiro item de uma lista tem um índice ordinal de zero. Se a posição solicitada não existir na lista, é gerado um erro.

  • Para uma tabela x e um número y, a linha da tabela x na posição y. Considera-se que a primeira linha de uma tabela tem um índice ordinal de zero. Se a posição solicitada não existir na tabela, um erro será gerado.

  • Para uma tabela x e um registro y, a linha da tabela x que corresponde aos valores de campo de registro y para campos com nomes de campo que correspondem aos nomes de colunas de tabela correspondentes. Se não houver nenhuma linha correspondente exclusiva na tabela, um erro será gerado.

Por exemplo:

{"a","b","c"}{0}                        // "a" 
{1, [A=2], 3}{1}                        // [A=2] 
{true, false}{2}                        // error 
#table({"A","B"},{{0,1},{2,1}}){0}      // [A=0,B=1] 
#table({"A","B"},{{0,1},{2,1}}){[A=2]}  // [A=2,B=1]  
#table({"A","B"},{{0,1},{2,1}}){[B=3]}  // error 
#table({"A","B"},{{0,1},{2,1}}){[B=1]}  // error

A expressão item-access-também suporta o formulário x{y}?, que retorna null quando a posição (ou correspondência) y não existe na lista ou tabela x. Se houver várias correspondências para yo , um erro ainda será gerado.

Por exemplo:

{"a","b","c"}{0}?                       // "a" 
{1, [A=2], 3}{1}?                       // [A=2] 
{true, false}{2}?                       // null 
#table({"A","B"},{{0,1},{2,1}}){0}?     // [A=0,B=1] 
#table({"A","B"},{{0,1},{2,1}}){[A=2]}? // [A=2,B=1]  
#table({"A","B"},{{0,1},{2,1}}){[B=3]}? // null 
#table({"A","B"},{{0,1},{2,1}}){[B=1]}? // error

O acesso ao item não força a avaliação de itens de lista ou tabela diferentes daquele que está sendo acessado. Por exemplo:

{ error "a", 1, error "c"}{1}  // 1 
{ error "a", error "b"}{1}     // error "b"

O seguinte vale quando o operador x{y} de acesso ao item é avaliado:

  • Erros levantados durante a avaliação de expressões x ou y são propagados.

  • A expressão x produz uma lista ou um valor de tabela.

  • A expressão y produz um valor numérico ou, se x produzir um valor de tabela, um valor de registro.

  • Se y produzir um valor numérico e o valor de for negativo, um erro com o código y de "Expression.Error" razão será gerado.

  • Se y produzir um valor numérico e o valor de for maior ou igual à contagem de , um erro com o código y de xrazão será gerado, a menos que o formulário "Expression.Error" de x{y}? operador opcional seja usado, caso em que o valor null será retornado.

  • Se x produzir um valor de tabela e y produzir um valor de registro e não houver correspondências para y em x, um erro com código "Expression.Error" de motivo será gerado, a menos que o formulário x{y}? de operador opcional seja usado, caso em que o valor null será retornado.

  • Se x produzir um valor de tabela e y produzir um valor de registro e houver várias correspondências para y em x, um erro com código "Expression.Error" de motivo será gerado.

Nenhum item x além daquele na posição y é avaliado durante o processo de seleção de itens. (Para listas ou tabelas de streaming, os itens ou linhas que precedem a posição y são ignorados, o que pode causar sua avaliação, dependendo da fonte da lista ou tabela.)

Acesso ao campo

A expressão field-access-é usada para selecionar um valor de um registro ou para projetar um registro ou tabela em um com menos campos ou colunas, respectivamente.

campo-acesso-expressão:
      seleção de campo
      implicit-target-field-selection
      projeção
      implicitidade-alvo-projeção
seleção de campos:
      seletor de campo de expressão primária
seletor de campo:
      seletor de campo obrigatório
      opcional-campo-seletor
seletor de campos obrigatórios:

       [ nome do campo]
opcional-campo-seletor:
       [ nome do campo] ?
nome do campo:
      identificador generalizado
      identificador cotado
seleção implícita-alvo-campo:
      seletor de campo
Projeção:
      projeção necessária de expressão primária
      expressão primária-opcional-projeção
Projeção necessária:

       [ lista de seletores obrigatórios ]
Opcional-Projeção:
       [ lista de seletores obrigatórios ] ?
lista de seletores obrigatórios:
      seletor de campo obrigatório
      required-selector-list
,required-field-selector
implicitidade-alvo-projeção:
      projeção necessária
      opcional-projeção

A forma mais simples de acesso ao campo é a seleção de campos obrigatórios. Ele usa o operador x[y] para procurar um campo em um registro por nome de campo. Se o campo y não existir no x, um erro será gerado. O formulário x[y]? é usado para executar a seleção de campo opcional e retorna null se o campo solicitado não existir no registro.

Por exemplo:

[A=1,B=2][B]       // 2 
[A=1,B=2][C]       // error 
[A=1,B=2][C]?      // null

O acesso coletivo de vários campos é suportado pelos operadores para projeção de registro necessária e projeção de registro opcional. O operador x[[y1],[y2],...] projeta o registro em um novo registro com menos campos (selecionado por y1, y2, ...). Se um campo selecionado não existir, um erro será gerado. O operador x[[y1],[y2],...]? projeta o registro em um novo registro com os campos selecionados por y1, y2, ...; se um campo estiver faltando, null é usado em vez disso. Por exemplo:

[A=1,B=2][[B]]           // [B=2] 
[A=1,B=2][[C]]           // error 
[A=1,B=2][[B],[C]]?      // [B=2,C=null]

Os formulários [y] e [y]? são suportados como uma referência abreviada para o identificador _ (sublinhado). As duas expressões seguintes são equivalentes:

[A]                 
_[A]

O exemplo a seguir ilustra a forma abreviada de acesso ao campo:

let _ = [A=1,B=2] in [A] //1

A forma [[y1],[y2],...] e [[y1],[y2],...]? também são suportados como uma abreviatura e as duas expressões a seguir são igualmente equivalentes:

[[A],[B]]                 
_[[A],[B]]

A forma abreviada é particularmente útil em combinação com a taquigrafia each , uma maneira de introduzir uma função de um único parâmetro chamado _ (para detalhes, consulte Declarações simplificadas). Juntas, as duas mãos curtas simplificam expressões funcionais comuns de ordem superior:

List.Select( {[a=1, b=1], [a=2, b=4]}, each [a] = [b]) 
// {[a=1, b=1]}

A expressão acima é equivalente à seguinte longhand de aparência mais enigmática:

List.Select( {[a=1, b=1], [a=2, b=4]}, (_) => _[a] = _[b]) 
// {[a=1, b=1]}

O acesso ao campo não obriga à avaliação de campos diferentes do(s) acedido(s). Por exemplo:

[A=error "a", B=1, C=error "c"][B]  // 1 
[A=error "a", B=error "b"][B]       // error "b"

O seguinte é válido quando um operador x[y]de acesso a campo , x[y]?, x[[y]], ou x[[y]]? é avaliado:

  • Os erros levantados durante a avaliação da expressão x são propagados.

  • Os erros gerados durante a avaliação do campo y são permanentemente associados ao campo ye, em seguida, propagados. Qualquer acesso futuro ao campo y gerará o mesmo erro.

  • A expressão x produz um valor de registro ou tabela, ou um erro é gerado.

  • Se o identificador y nomear um campo que não existe no x, um erro com o código "Expression.Error" de motivo será gerado, a menos que o formulário ...? de operador opcional seja usado, caso em que o valor null será retornado.

Nenhum campo diferente daquele x nomeado por y é avaliado durante o processo de acesso ao campo.

Operador de metadados

O registro de metadados para um valor é alterado usando o operador meta (x meta y).

expressão de metadados:
      unário-expressão
      unary-expression
metaunary-expression

O exemplo a seguir constrói um valor de texto com um registro de metadados usando o meta operador e, em seguida, acessa o registro de metadados do valor resultante usando Value.Metadata:

Value.Metadata( "Mozart" meta [ Rating = 5 ] ) 
// [Rating = 5 ]
Value.Metadata( "Mozart" meta [ Rating = 5 ] )[Rating] 
// 5

O seguinte vale ao aplicar o operador x meta yde combinação de metadados:

  • Os erros gerados ao avaliar as x expressões ou y são propagados.

  • A y expressão deve ser um registro ou um erro com o código "Expression.Error" de razão é gerado.

  • O registro de metadados resultante é xo registro de metadados do mesclado com yo . (Para a semântica da mesclagem de registros, consulte Mesclagem de registros.)

  • O valor resultante é o x valor da expressão, sem seus metadados, com o registro de metadados recém-computado anexado.

A biblioteca padrão funciona Value.RemoveMetadata e Value.ReplaceMetadata pode ser usada para remover todos os metadados de um valor e substituir os metadados de um valor (em vez de mesclar metadados em metadados possivelmente existentes). As seguintes expressões são equivalentes:

x meta y  
Value.ReplaceMetadata(x, Value.Metadata(x) & y) 
Value.RemoveMetadata(x) meta (Value.Metadata(x) & y)

Operadores de igualdade

O operador= de igualdade é usado para determinar se dois valores são iguais. O operador<> de desigualdade é usado para determinar se dois valores não são iguais.

igualdade-expressão:
      expressão-relacional
      relacional-expressão
=igualdade-expressão
      relacional-expressão
<>igualdade-expressão

Por exemplo:

1 = 1            // true 
1 = 2            // false 
1 <> 1           // false 
1 <> 2           // true 
null = true      // false 
null = null      // true

Os metadados não fazem parte da comparação de igualdade ou desigualdade. Por exemplo:

(1 meta [ a = 1 ]) = (1 meta [ a = 2 ]) // true 
(1 meta [ a = 1 ]) = 1                  // true

O seguinte se aplica ao aplicar os operadores x = y de igualdade e x <> y:

  • Os erros gerados ao avaliar as x expressões ou y são propagados.

  • O = operador tem um resultado de se os valores são iguais, e true de false outra forma.

  • O <> operador tem um resultado de se os valores são iguais, e false de true outra forma.

  • Os registos de metadados não são incluídos na comparação.

  • Se os valores produzidos pela avaliação das x expressões e y não são o mesmo tipo de valor, então os valores não são iguais.

  • Se os valores produzidos pela avaliação da x expressão e y são do mesmo tipo de valor, então existem regras específicas para determinar se eles são iguais, conforme definido abaixo.

  • O seguinte é sempre verdadeiro:

    (x = y) = not (x <> y)

Os operadores de igualdade são definidos para os seguintes tipos:

  • O null valor é apenas igual a si mesmo.
    null = null    // true 
    null = true    // false 
    null = false   // false
  • Os valores true lógicos e false são apenas iguais a si mesmos. Por exemplo:
    true = true      // true 
    false = false    // true 
    true = false     // false 
    true = 1         // false
  • Os números são comparados utilizando a precisão especificada:

    • Se um dos números for #nan, então os números não são os mesmos.

    • Quando nenhum dos números é #nan, então os números são comparados usando uma comparação bit a bit do valor numérico.

    • #nan é o único valor que não é igual a si mesmo.

      Por exemplo:

        1 = 1,              // true 
        1.0 = 1             // true 
        2 = 1               // false 
        #nan = #nan         // false 
        #nan <> #nan        // true
  • Duas durações são iguais se representarem o mesmo número de carrapatos de 100 nanossegundos.

  • Duas vezes são iguais se as magnitudes de suas partes (hora, minuto, segundo) forem iguais.

  • Duas datas são iguais se as magnitudes de suas partes (ano, mês, dia) forem iguais.

  • Dois datetimes são iguais se as magnitudes de suas partes (ano, mês, dia, hora, minuto, segundo) forem iguais.

  • Dois fusos datetime são iguais se as datetimes UTC correspondentes forem iguais. Para chegar ao datetime UTC correspondente, o deslocamento de horas/minutos é subtraído do componente datetime do datetimezone.

  • Dois valores de texto são iguais se, usando uma comparação ordinal, sensível a maiúsculas e minúsculas e sem distinção de cultura, eles tiverem o mesmo comprimento e caracteres iguais nas posições correspondentes.

  • Dois valores de lista serão iguais se todos os itens a seguir forem verdadeiros:

    • Ambas as listas contêm o mesmo número de itens.

    • Os valores de cada item correspondente posicionalmente nas listas são iguais. Isso significa que não apenas as listas precisam conter itens iguais, mas os itens precisam estar na mesma ordem.

      Por exemplo:

        {1, 2} = {1, 2}     // true 
        {2, 1} = {1, 2}     // false 
        {1, 2, 3} = {1, 2}  // false
      
  • Dois registros serão iguais se todos os itens a seguir forem verdadeiros:

    • O número de campos é o mesmo.

    • Cada nome de campo de um registro também está presente no outro registro.

    • O valor de cada campo de um registo é igual ao campo com o mesmo nome no outro registo.

      Por exemplo:

        [ A = 1, B = 2 ] = [ A = 1, B = 2 ]        // true 
        [ B = 2, A = 1 ] = [ A = 1, B = 2 ]        // true 
        [ A = 1, B = 2, C = 3 ] = [ A = 1, B = 2 ] // false 
        [ A = 1 ] = [ A = 1, B = 2 ]               // false
      
  • Duas tabelas são iguais se todas as seguintes opções forem verdadeiras:

    • O número de colunas é o mesmo.

    • Cada nome de coluna em uma tabela também está presente na outra tabela.

    • O número de linhas é o mesmo.

    • Cada linha tem valores iguais nas células correspondentes.

      Por exemplo:

        #table({"A","B"},{{1,2}}) = #table({"A","B"},{{1,2}}) // true 
        #table({"A","B"},{{1,2}}) = #table({"X","Y"},{{1,2}}) // false 
        #table({"A","B"},{{1,2}}) = #table({"B","A"},{{2,1}}) // true
      
  • Um valor de função é igual a si mesmo, mas pode ou não ser igual a outro valor de função. Se dois valores de função forem considerados iguais, eles se comportarão de forma idêntica quando invocados.

    Dois valores de função dados terão sempre a mesma relação de igualdade.

  • Um valor de tipo é igual a si mesmo, mas pode ou não ser igual a outro valor de tipo. Se dois valores de tipo forem considerados iguais, eles se comportarão de forma idêntica quando consultados quanto à conformidade.

    Dois valores de tipo dados terão sempre a mesma relação de igualdade.

Operadores relacionais

Os <operadores , >, <=, e >= são chamados de operadores relacionais.

expressão-relacional:
      expressão-aditiva
      expressão-aditiva-relacional-expressão
<
      expressão-aditiva-relacional-expressão
>
      expressão-aditiva-relacional-expressão
<=
      expressão-aditiva-relacional-expressão
>=

Esses operadores são usados para determinar a relação de ordenação relativa entre dois valores, conforme mostrado na tabela a seguir:

Operação Result
x < y true se x for inferior a y, false caso contrário
x > y true se x for maior que y, false caso contrário
x <= y true se x for menor ou igual a y, false caso contrário
x >= y true se x for maior ou igual a y, false caso contrário

Por exemplo:

0 <= 1            // true 
null < 1          // null 
null <= null      // null 
"ab" < "abc"      // true 
#nan >= #nan      // false  
#nan <= #nan      // false

O seguinte vale ao avaliar uma expressão que contém os operadores relacionais:

  • Os erros gerados ao avaliar as expressões ou x operando y são propagados.

  • Os valores produzidos pela avaliação das x expressões e y devem ser um valor binário, date, datetime, datetimezone, duration, logical, number, null, text ou time. Caso contrário, um erro com o código "Expression.Error" de razão é gerado.

  • Ambos os operandos devem ser do mesmo tipo de valor ou null. Caso contrário, um erro com o código "Expression.Error" de razão é gerado.

  • Se um ou ambos os operandos forem null, o resultado será o null valor.

  • Dois binários são comparados byte por byte.

  • Duas datas são comparadas comparando as partes do ano e, se iguais, as partes do mês e, se iguais, as partes do dia.

  • Duas datas-tempos são comparadas comparando as suas partes do ano e, se iguais, as partes do mês e, se iguais, as partes do dia e, se iguais, as partes da hora e, se iguais, as partes minúsculas e, se iguais, as segundas partes.

  • Dois fusos datetime são comparados normalizando-os para UTC subtraindo seu deslocamento hora/minuto e, em seguida, comparando seus componentes datetime.

  • Duas durações são comparadas de acordo com o número total de carrapatos de 100 nanossegundos que representam.

  • Duas lógicas são comparadas de tal forma que é considerado maior do trueque false .

  • Dois números x e y são comparados de acordo com as regras do padrão IEEE 754:

    • Se qualquer um dos operandos for #nan, o resultado será false para todos os operadores relacionais.

    • Quando nenhum dos operandos é #nan, os operadores comparam os valores dos dois operandos de ponto flutuante em relação à ordenação -∞ < -max < ... < -min < -0.0 = +0.0 < +min < ... < +max < +∞ , onde min e max são os menores e maiores valores finitos positivos que podem ser representados. Os nomes M para -∞ e +∞ são -#infinity e #infinity.

      Efeitos notáveis desta ordenação são:

      • Os zeros negativos e positivos são considerados iguais.

      • Um -#infinity valor é considerado menor do que todos os outros valores numéricos, mas igual a outro -#infinity.

      • Um #infinity valor é considerado maior do que todos os outros valores numéricos, mas igual a outro #infinity.

  • Dois textos são comparados usando uma comparação ordinal caractere a caractere, sensível a maiúsculas e minúsculas e insensível à cultura.

  • Duas vezes são comparadas comparando suas partes de hora e, se iguais, suas partes minúsculas e, se iguais, suas segundas partes.

Operadores lógicos condicionais

Os and operadores e or são chamados de operadores lógicos condicionais.

lógica-ou-expressão:
      lógica-e-expressão-lógica-e-expressão-lógica-ou-expressão
or
lógica-e-expressão:
      é-expressão
      é-expressão-lógica-e-expressão
and

O or operador retorna true quando pelo menos um de seus operandos é true. O operando direito é avaliado se e somente se o operando esquerdo não truefor .

O and operador retorna false quando pelo menos um de seus operandos é false. O operando direito é avaliado se e somente se o operando esquerdo não falsefor .

As tabelas de verdade para os or operadores e and são mostradas abaixo, com o resultado da avaliação da expressão do operando esquerdo no eixo vertical e o resultado da avaliação da expressão do operando direito no eixo horizontal.

and true false null error
true true false null error
false false false false false
null null false null error
error error error error error
or true false null error
or true false null error
true true true true true
false true false null error
null true null null error
error error error error error

O seguinte vale ao avaliar uma expressão que contém operadores lógicos condicionais:

  • Os erros gerados ao avaliar as x expressões ou y são propagados.

  • Os operadores lógicos condicionais são definidos sobre os tipos logical e null. Se os valores do operando não forem desses tipos, um erro com o código "Expression.Error" de motivo será gerado.

  • O resultado é um valor lógico.

  • Na expressão x ou y, a expressão y será avaliada se e somente se x não avaliar a true.

  • Na expressão x e y, a expressão y será avaliada se e somente se x não avaliar a false.

As duas últimas propriedades dão aos operadores lógicos condicionais sua qualificação "condicional"; propriedades também referidas como "curto-circuito". Essas propriedades são úteis para escrever predicados compactos protegidos. Por exemplo, as seguintes expressões são equivalentes:

d <> 0 and n/d > 1 if d <> 0 then n/d > 1 else false

Operadores Aritméticos

Os +operadores , -*, e / são os operadores aritméticos.

expressão-aditiva:
      Expressão multiplicativa
      expressão-aditiva-multiplicativa-expressão
+
      expressão-aditiva-multiplicativa-expressão
-
Expressão multiplicativa:
      metadados- expressão
      expressão multiplicativa-expressão
*de metadados
      expressão multiplicativa-expressão
/de metadados

Precisão

Os números em M são armazenados usando uma variedade de representações para reter o máximo de informações possível sobre números provenientes de uma variedade de fontes. Os números só são convertidos de uma representação para outra conforme a necessidade dos operadores aplicados a eles. Duas precisões são suportadas em M:

Precisão Semântica
Precision.Decimal Representação decimal de 128 bits com um intervalo de ±1,0 x 10-28 a ±7,9 x 1028 e 28-29 dígitos significativos.
Precision.Double Representação científica utilizando mantissa e expoente; está em conformidade com o padrão aritmético binário de precisão dupla IEEE 754 IEEE 754-2008 de 64 bits.

As operações aritméticas são realizadas escolhendo uma precisão, convertendo ambos os operandos para essa precisão (se necessário), executando a operação real e, finalmente, retornando um número na precisão escolhida.

Os operadores aritméticos integrados (+, -, *, /) usam precisão dupla. As funções padrão da biblioteca (Value.Add, Value.Subtract, Value.Multiply, Value.Divide) podem ser usadas para solicitar essas operações usando um modelo de precisão específico.

  • Nenhum estouro numérico é possível: #infinity ou -#infinity representam valores de grandezas muito grandes para serem representados.

  • Nenhum subfluxo numérico é possível: 0 e -0 representam valores de grandezas muito pequenas para serem representados.

  • O valor #nan especial IEEE 754 (NaN—Not a Number) é usado para cobrir casos aritmicamente inválidos, como uma divisão de zero por zero.

  • A conversão de precisão decimal para dupla é realizada arredondando números decimais para o valor duplo equivalente mais próximo.

  • A conversão de precisão dupla para decimal é realizada arredondando números duplos para o valor decimal equivalente mais próximo e, se necessário, transbordando para #infinity ou -#infinity valores.

operador de adição

A interpretação do operador de adição (x + y) depende do tipo de valor das expressões avaliadas x e y, da seguinte forma:

x S Result Interpretação
type number type number type number Soma numérica
type number null null
null type number null
type duration type duration type duration Soma numérica de grandezas
type duration null null
null type duration null
type datetime type duration type datetime Data/hora deslocada por duração
type duration type datetime type datetime
type datetime null null
null type datetime null

Na tabela, typedatetime significa qualquer um dos type date, type datetime, type datetimezone, ou type time. Ao adicionar uma duração e um valor de algum tipo datetime, o valor resultante é desse mesmo tipo.

Para outras combinações de valores além das listadas na tabela, um erro com o código "Expression.Error" de motivo é gerado. Cada combinação é abordada nas seções a seguir.

Os erros gerados ao avaliar qualquer operando são propagados.

Soma numérica

A soma de dois números é calculada usando o operador de adição, produzindo um número.

Por exemplo:

1 + 1             // 2 
#nan + #infinity  // #nan

O operador + de adição sobre números usa Precisão Dupla, a função Value.Add de biblioteca padrão pode ser usada para especificar Precisão Decimal. O seguinte vale ao calcular uma soma de números:

  • A soma em Precisão Dupla é calculada de acordo com as regras de precisão dupla binária de 64 bits IEEE 754 aritmética IEEE 754-2008. A tabela a seguir lista os resultados de todas as combinações possíveis de valores finitos diferentes de zero, zeros, infinidades e NaN's. Na tabela, x e são valores finitos diferentes de zero, e y é o resultado de zx + y . Se x e y têm a mesma magnitude mas sinais opostos, z é zero positivo. Se x + y for muito grande para ser representado no tipo de destino, z é um infinito com o mesmo sinal x + yque .

    + S +0 0- +∞ -∞ NaN
    x z x x +∞ -∞ NaN
    +0 S +0 +0 +∞ -∞ NaN
    -0 S +0 0- +∞ -∞ NaN
    +∞ +∞ +∞ +∞ +∞ NaN NaN
    -∞ -∞ -∞ -∞ NaN -∞ NaN
    NaN NaN NaN NaN NaN NaN NaN
  • A soma em precisão decimal é calculada sem perder a precisão. A escala do resultado é a maior das escalas dos dois operandos.

Soma das durações

A soma de duas durações é a duração que representa a soma do número de carrapatos de 100 nanossegundos representados pelas durações. Por exemplo:

#duration(2,1,0,15.1) + #duration(0,1,30,45.3) 
// #duration(2, 2, 31, 0.4)

Data/hora deslocada por duração

Uma e uma duração x podem ser adicionadas usando y para calcular uma nova x + y cuja distância de uma linha do tempo linear é exatamente a magnitude de x. Aqui, datetime significa qualquer um dos Date, DateTime, DateTimeZone, ou Time e um resultado não nulo será do mesmo tipo. O deslocamento datetime por duração pode ser calculado da seguinte forma:

  • Se o valor datetime days since epoch for especificado, construa um novo datetime com os seguintes elementos de informação:

    • Calcule um novo dia desde a época equivalente a dividir a magnitude de y pelo número de ticks de 100 nanossegundos em um período de 24 horas, truncando a porção decimal do resultado e adicionando esse valor aos dias de x desde a época.

    • Calcule um novo ticks desde a meia-noite equivalente a adicionar a magnitude de y aos ticks do x desde a meia-noite, modulo o número de ticks de 100 nanossegundos em um período de 24 horas. Se x não especificar um valor para ticks desde a meia-noite, um valor de 0 será assumido.

    • Copie o valor de x para minutos deslocados do UTC inalterado.

  • Se o valor datetime days since epoch não for especificado, construa um novo datetime com os seguintes elementos de informação especificados:

    • Calcule um novo ticks desde a meia-noite equivalente a adicionar a magnitude de y aos ticks do x desde a meia-noite, modulo o número de ticks de 100 nanossegundos em um período de 24 horas. Se x não especificar um valor para ticks desde a meia-noite, um valor de 0 será assumido.

    • Copie os valores de x por dias desde a época e minutos deslocados do UTC inalterado.

Os exemplos a seguir mostram o cálculo da soma temporal absoluta quando a datetime especifica os dias desde a época:

#date(2010,05,20) + #duration(0,8,0,0) 
    //#datetime( 2010, 5, 20, 8, 0, 0 ) 
    //2010-05-20T08:00:00 
 
#date(2010,01,31) + #duration(30,08,0,0) 
    //#datetime(2010, 3, 2, 8, 0, 0) 
    //2010-03-02T08:00:00 
 
#datetime(2010,05,20,12,00,00,-08) + #duration(0,04,30,00) 
    //#datetime(2010, 5, 20, 16, 30, 0, -8, 0) 
    //2010-05-20T16:30:00-08:00 
 
#datetime(2010,10,10,0,0,0,0) + #duration(1,0,0,0) 
   //#datetime(2010, 10, 11, 0, 0, 0, 0, 0) 
   //2010-10-11T00:00:00+00:00

O exemplo a seguir mostra o cálculo do deslocamento datetime por duração para um determinado tempo:

#time(8,0,0) + #duration(30,5,0,0) 
   //#time(13, 0, 0) 
   //13:00:00

operador de subtração

A interpretação do operador de subtração (x - y) depende do tipo de valor das expressões x avaliadas e y, da seguinte forma:

x Y Result Interpretação
type number type number type number Diferença numérica
type number null null
null type number null
type duration type duration type duration Diferença numérica de magnitudes
type duration null null
null type duration null
type datetime type datetime type duration Duração entre datetimes
type datetime type duration type datetime Data/hora compensada pela duração negada
type datetime null null
null type datetime null

Na tabela, typedatetime significa qualquer um dos type date, type datetime, type datetimezone, ou type time. Ao subtrair uma duração de um valor de algum tipo datetime, o valor resultante é desse mesmo tipo.

Para outras combinações de valores além das listadas na tabela, um erro com o código "Expression.Error" de motivo é gerado. Cada combinação é abordada nas seções a seguir.

Os erros gerados ao avaliar qualquer operando são propagados.

Diferença numérica

A diferença entre dois números é calculada usando o operador de subtração, produzindo um número. Por exemplo:

1 - 1                // 0 
#nan - #infinity     // #nan

O operador - de subtração sobre números usa Precisão Dupla, a função Value.Subtract de biblioteca padrão pode ser usada para especificar Precisão Decimal. O seguinte vale ao calcular uma diferença de números:

  • A diferença na Precisão Dupla é calculada de acordo com as regras da aritmética IEEE 754-2008 IEEE 754-2008 de precisão dupla binária de 64 bits. A tabela a seguir lista os resultados de todas as combinações possíveis de valores finitos diferentes de zero, zeros, infinidades e NaN's. Na tabela, x e são valores finitos diferentes de zero, e y é o resultado de zx - y . Se x e y são iguais, z é zero positivo. Se x - y for muito grande para ser representado no tipo de destino, z é um infinito com o mesmo sinal x - yque .

    - S +0 0- +∞ -∞ NaN
    x z x x -∞ +∞ NaN
    +0 -y +0 +0 -∞ +∞ NaN
    -0 -y 0- +0 -∞ +∞ NaN
    +∞ +∞ +∞ +∞ NaN +∞ NaN
    -∞ -∞ -∞ -∞ -∞ NaN NaN
    NaN NaN NaN NaN NaN NaN NaN
  • A diferença na precisão decimal é calculada sem perder a precisão. A escala do resultado é a maior das escalas dos dois operandos.

Diferença de durações

A diferença de duas durações é a duração que representa a diferença entre o número de ticks de 100 nanossegundos representados por cada duração. Por exemplo:

#duration(1,2,30,0) - #duration(0,0,0,30.45) 
// #duration(1, 2, 29, 29.55)

Data/hora compensada pela duração negada

Uma data/horax e uma duração y podem ser subtraídas usando x - y para calcular uma nova data/hora. Aqui, datetime significa qualquer um dos date, datetime, datetimezone, ou time. O datetime resultante . Subtrair durações positivas produz resultados que estão atrasados no tempo em relação ao , enquanto subtrair xvalores negativos produz resultados que são avançados no tempo.

#date(2010,05,20) - #duration(00,08,00,00) 
   //#datetime(2010, 5, 19, 16, 0, 0) 
   //2010-05-19T16:00:00 
#date(2010,01,31) - #duration( 30,08,00,00) 
   //#datetime(2009, 12, 31, 16, 0, 0) 
   //2009-12-31T16:00:00

Duração entre duas datas/hora

Duas datas/horat e u podem ser subtraídas usando t - u para calcular a duração entre elas. Aqui, datetime significa qualquer um dos date, datetime, datetimezone, ou time. A duração produzida por subtração u do mosto produz t quando adicionada t a u.

#date(2010,01,31) - #date(2010,01,15) 
// #duration(16,00,00,00) 
// 16.00:00:00 
 
#date(2010,01,15)- #date(2010,01,31) 
// #duration(-16,00,00,00) 
// -16.00:00:00 
 
#datetime(2010,05,20,16,06,00,-08,00) - 
#datetime(2008,12,15,04,19,19,03,00) 
// #duration(521,22,46,41)
// 521.22:46:41

Subtrair t - u quando u > t resulta numa duração negativa:

#time(01,30,00) - #time(08,00,00) 
// #duration(0, -6, -30, 0)

O seguinte vale ao subtrair duas datetimes usando t - u:

  • u + (t - u) = t

operador de multiplicação

A interpretação do operador de multiplicação (x * y) depende do tipo de valor das expressões avaliadas x e y, da seguinte forma:

X Y Result Interpretação
type number type number type number Produto numérico
type number null null
null type number null
type duration type number type duration Múltiplos de duração
type number type duration type duration Múltiplos de duração
type duration null null
null type duration null

Para outras combinações de valores além das listadas na tabela, um erro com o código "Expression.Error" de motivo é gerado. Cada combinação é abordada nas seções a seguir.

Os erros gerados ao avaliar qualquer operando são propagados.

Produto numérico

O produto de dois números é calculado usando o operador de multiplicação, produzindo um número. Por exemplo:

2 * 4                // 8 
6 * null             // null 
#nan * #infinity     // #nan

O operador * de multiplicação sobre números usa Precisão Dupla, a função Value.Multiply de biblioteca padrão pode ser usada para especificar Precisão Decimal. O seguinte vale ao calcular um produto de números:

  • O produto em Double Precision é calculado de acordo com as regras de 64-bit binário de dupla precisão IEEE 754 aritmética IEEE 754-2008. A tabela a seguir lista os resultados de todas as combinações possíveis de valores finitos diferentes de zero, zeros, infinidades e NaN's. Na tabela, x e y são valores finitos positivos. z é o resultado de x * y. Se o resultado for muito grande para o tipo de destino, z é infinito. Se o resultado for muito pequeno para o tipo de destino, z é zero.

    * +y -y +0 0- +∞ -∞ NaN
    +x +z -z +0 0- +∞ -∞ NaN
    -x -z +z 0- +0 -∞ +∞ NaN
    +0 +0 0- +0 0- NaN NaN NaN
    -0 0- +0 0- +0 NaN NaN NaN
    +∞ +∞ -∞ NaN NaN +∞ -∞ NaN
    -∞ -∞ +∞ NaN NaN -∞ +∞ NaN
    NaN NaN NaN NaN NaN NaN NaN NaN
  • O produto em Precisão Decimal é calculado sem perder a precisão. A escala do resultado é a maior das escalas dos dois operandos.

Múltiplos de durações

O produto de uma duração e um número é a duração que representa o número de ticks de 100nanossegundos representado pelo operando de duração vezes o operando de número. Por exemplo:

#duration(2,1,0,15.1) * 2 
// #duration(4, 2, 0, 30.2)

operador de divisão

A interpretação do operador de divisão (x / y) depende do tipo de valor das expressões x avaliadas e y, da seguinte forma:

X Y Result Interpretação
type number type number type number Quociente numérico
type number null null
null type number null
type duration type number type duration Fração de duração
type duration type duration type number Quociente numérico de durações
type duration null null
null type duration null

Para outras combinações de valores além das listadas na tabela, um erro com o código "Expression.Error" de motivo é gerado. Cada combinação é abordada nas seções a seguir.

Os erros gerados ao avaliar qualquer operando são propagados.

Quociente numérico

O quociente de dois números é calculado usando o operador de divisão, produzindo um número. Por exemplo:

8 / 2               // 4 
8 / 0               // #infinity 
0 / 0               // #nan 
0 / null            // null 
#nan / #infinity    // #nan

O operador / de divisão sobre números usa Precisão Dupla, a função Value.Divide de biblioteca padrão pode ser usada para especificar Precisão Decimal. O seguinte vale ao calcular um quociente de números:

  • O quociente em Precisão Dupla é calculado de acordo com as regras de precisão dupla binária de 64 bits IEEE 754 aritmética IEEE 754-2008. A tabela a seguir lista os resultados de todas as combinações possíveis de valores finitos diferentes de zero, zeros, infinidades e NaN's. Na tabela, x e y são valores finitos positivos. z é o resultado de x / y. Se o resultado for muito grande para o tipo de destino, z é infinito. Se o resultado for muito pequeno para o tipo de destino, z é zero.

    / +y -y +0 0- +∞ -∞ NaN
    +x +z -z +∞ -∞ +0 0- NaN
    -x -z +z -∞ +∞ 0- +0 NaN
    +0 +0 0- NaN NaN +0 0- NaN
    -0 0- +0 NaN NaN 0- +0 NaN
    +∞ +∞ -∞ +∞ -∞ NaN NaN NaN
    -∞ -∞ +∞ -∞ +∞ NaN NaN NaN
    NaN NaN NaN NaN NaN NaN NaN NaN
  • A soma em precisão decimal é calculada sem perder a precisão. A escala do resultado é a maior das escalas dos dois operandos.

Quociente de durações

O quociente de duas durações é o número que representa o quociente do número de ticks de 100nanossegundos representado pelas durações. Por exemplo:

#duration(2,0,0,0) / #duration(0,1,30,0) 
// 32

Durações dimensionadas

O quociente de uma duração x e um número y é a duração que representa o quociente do número de carrapatos de 100 nanossegundos representado pela duração x e pelo número y. Por exemplo:

#duration(2,0,0,0) / 32 
// #duration(0,1,30,0)

Combinação de estruturas

O operador de combinação (x & y) é definido sobre os seguintes tipos de valores:

X Y Result Interpretação
type text type text type text Concatenação
type text null null
null type text null
type date type time type datetime Unir
type date null null
null type time null
type list type list type list Concatenação
type record type record type record Unir
type table type table type table Concatenação

Concatenação

Dois valores de texto, duas listas ou duas tabelas podem ser concatenados usando x & y.

O exemplo a seguir ilustra a concatenação de valores de texto:

"AB" & "CDE"     // "ABCDE"

O exemplo a seguir ilustra listas concatenadoras:

{1, 2} & {3}     // {1, 2, 3}

O seguinte vale ao concatenar dois valores usando x & y:

  • Os erros gerados ao avaliar as x expressões ou y são propagados.

  • Nenhum erro é propagado se um item de um ou xy contém um erro.

  • O resultado da concatenação de dois valores de texto é um valor de texto que contém o valor de x imediatamente seguido por y. Se um dos operandos for nulo e o outro for um valor de texto, o resultado será nulo.

  • O resultado da concatenação de duas listas é uma lista que contém todos os itens de x seguido por todos os itens de y.

  • O resultado da concatenação de duas tabelas é uma tabela que tem a união das duas colunas da tabela de operando. A ordenação das colunas é x preservada, seguida pelas colunas que aparecem apenas em y, preservando a sua ordem relativa. Para colunas que aparecem apenas em um dos operandos, null é usado para preencher valores de célula para o outro operando.

Unir

Mesclagem de registros

Dois registros podem ser mesclados usando x & y, produzindo um registro que inclui campos de ambos e xy .

Os exemplos a seguir ilustram a fusão de registros:

[ x = 1 ] & [ y = 2 ]                // [ x = 1, y = 2 ] 
[ x = 1, y = 2 ] & [ x = 3, z = 4 ]  // [ x = 3, y = 2, z = 4 ]

O seguinte é válido ao mesclar dois registros usando x + y:

  • Os erros gerados ao avaliar as x expressões ou y são propagados.

  • Se um campo aparecer em ambos x e y, o valor de y é usado.

  • A ordem dos campos no registro resultante é a de , seguida pelos xcampos em y que não fazem parte de x, na mesma ordem em que aparecem em y.

  • A fusão de registros não causa avaliação dos valores.

  • Nenhum erro é gerado porque um campo contém um erro.

  • O resultado é um recorde.

Mesclagem data-hora

Uma data x pode ser mesclada com uma hora y usando x & y, produzindo uma data/hora que combina as partes de ambos e xy.

O exemplo a seguir ilustra a fusão de uma data e uma hora:

#date(2013,02,26) & #time(09,17,00) 
// #datetime(2013,02,26,09,17,00)

O seguinte é válido ao mesclar dois registros usando x + y:

  • Os erros gerados ao avaliar as x expressões ou y são propagados.

  • O resultado é uma data/hora.

Operadores unários

O +, -e not operadores são operadores unários.

unário-expressão:
      tipo-expressão

       + Expressão unária
       - Expressão unária
       not Expressão unária

Unary plus operador

O operador unary plus (+x) é definido para os seguintes tipos de valores:

X Result Interpretação
type number type number Unário mais
type duration type duration Unário mais
null «Nulo

Para outros valores, um erro com código "Expression.Error" de motivo é gerado.

O operador unary plus permite que um + sinal seja aplicado a um número, datetime ou valor nulo. O resultado é esse mesmo valor. Por exemplo:

+ - 1                 // -1 
+ + 1                 // 1 
+ #nan                // #nan 
+ #duration(0,1,30,0) // #duration(0,1,30,0)

Ao avaliar o operador +xunary plus, é válido o seguinte:

  • Os erros gerados durante a avaliação x são propagados.

  • Se o resultado da avaliação x não for um valor numérico, um erro com o código "Expression.Error" de razão será gerado.

Unary menos operador

O operador unário menos (-x) é definido para os seguintes tipos de valores:

X Result Interpretação
type number type number Negação
type duration type duration Negação
null null

Para outros valores, um erro com código "Expression.Error" de motivo é gerado.

O operador unário menos é usado para alterar o sinal de um número ou duração. Por exemplo:

- (1 + 1)       // -2 
- - 1           // 1 
- - - 1         // -1 
- #nan          // #nan 
- #infinity     // -#infinity 
- #duration(1,0,0,0)  // #duration(-1,0,0,0) 
- #duration(0,1,30,0) // #duration(0,-1,-30,0)

Ao avaliar o operador -xunário menos :

  • Os erros gerados durante a avaliação x são propagados.

  • Se a expressão for um número, o resultado será o valor numérico da expressão x com seu sinal alterado. Se o valor for NaN, então o resultado também é NaN.

Operador de negação lógica

O operador de negação lógica (not) é definido para os seguintes tipos de valores:

X Result Interpretação
type logical type logical Negação
null null

Este operador calcula a operação lógica not em um determinado valor lógico. Por exemplo:

not true             // false 
not false            // true 
not (true and true)  // false

O seguinte vale ao avaliar o operador not xde negação lógica:

  • Os erros gerados durante a avaliação x são propagados.

  • O valor produzido a partir da avaliação da expressão x deve ser um valor lógico ou um erro com o código "Expression.Error" de razão deve ser gerado. Se o valor for true, o resultado será false. Se o operando for false, o resultado será true.

O resultado é um valor lógico.

Operadores de tipo

Os operadores is e as são conhecidos como os operadores de tipo.

Operador de compatibilidade de tipo

O operador x is y de compatibilidade de tipo é definido para os seguintes tipos de valores:

X Y Result
type any nullable-primitive-type type logical

A expressão x is y retorna true se o tipo atribuído de x é compatível com y, e retorna false se o tipo atribuído de x é incompatível com y. y deve ser um tipo primitivo nulo.

é-expressão:
      como-expressão
      is-expression
isnullable-primitive-type
nullable-primitive-type:

       nullable opt primitivo-tipo

A compatibilidade de tipo, conforme suportado is pelo operador, é um subconjunto da compatibilidade geral de tipo e é definida usando as seguintes regras:

  • Se x é nulo, então é compatível se y é o tipo any, o tipo null, ou um tipo anulável.

  • Se x é não-nulo, então se é um compatível, se o tipo primitivo de x é o mesmo que y.

Ao avaliar a expressão x is y, é válido o seguinte:

  • Um erro gerado ao avaliar a expressão x é propagado.

Operador de asserção de tipo

O operador x as y de asserção de tipo é definido para os seguintes tipos de valores:

X Y Result
type any nullable-primitive-type type any

A expressão x as y afirma que o valor x é compatível com o operador de acordo com y o is operador. Se não for compatível, um erro é gerado. y deve ser um tipo primitivo anulável.

Como expressão:
      igualdade-expressão
      as-expression
asnullable-primitive-type

A expressão x as y é avaliada da seguinte forma:

  • Uma verificação x is y de compatibilidade de tipo é executada e a asserção retorna x inalterada se o teste for bem-sucedido.

  • Se a verificação de compatibilidade falhar, um erro com o código "Expression.Error" de motivo será gerado.

Exemplos:

1 as number               // 1 
"A" as number             // error 
null as nullable number   // null

Ao avaliar a expressão x as y, é válido o seguinte:

  • Um erro gerado ao avaliar a expressão x é propagado.

Operador de coalesce

O operador ?? coalesce retorna o resultado de seu operando esquerdo se ele não for nulo, caso contrário, ele retornará o resultado de seu operando direito. O operando direito é avaliado se e somente se o operando esquerdo for nulo.