Compartilhar via


Comportamento do operador

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

Precedência do operador

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 precedência maior do que o operador binário +. A precedência de um operador é estabelecida pela definição da sua produção de gramática associada. Por exemplo, uma expressão-aditiva consiste em uma sequência de produções de expressão-multiplicativa separadas por operadores + ou -, permitindo assim que os operadores + e - tenham mais precedências do que os operadores * e /.

A produção expressão-entre-parênteses pode ser usada para alterar a ordenação 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 operador em ordem de precedência, da mais alta para a mais baixa. Os operadores em uma mesma categoria têm precedência igual.

Categoria Expressão Descrição
Primária i
@i
Expressão de identificador
(x) Expressão entre parênteses
x[i] Lookup
x{y} Acesso ao item
x(...) Invocação de função
{x, y, ...} Inicialização de lista
[ i = x, ... ] Inicialização de registro
... Não implementado
Unário +x Identity
-x Negação
notx Negação lógica
Metadados xmetay Associar metadados
Multiplicativo x * y Multiplicação
x / y Divisão
Aditiva x + y Adição
x - y Subtração
Relacional x< y Menor que
x > y Maior que
x<= y Inferior ou igual
x >= y Maior ou igual
Igualitário x = y Igual
x<> y Diferente
Asserção de tipo xasy É um tipo primitivo que permite valor nulo ou então resulta em erro
Conformidade de tipo xisy Testar se o tipo primitivo que permite valor nulo é compatível
AND lógico xandy Conjunção de curto-circuito
OR lógico xory Disjunção de curto-circuito
Coalesce x??y Operador de união nula

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, mesmo null. O resultado dessa associação é um novo valor com os metadados fornecidos.

Um registro de metadados é apenas um registro comum e pode conter os mesmos tipos de campos e valores que um registro regular, além de conter um registro de metadados. Associar um registro de metadados com um valor é uma ação "não intrusiva". Essa associação não altera o comportamento do valor em avaliações, exceto aqueles 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 é vazio. Os exemplos a seguir mostram como acessar o registro de metadados de um valor de texto usando a função de biblioteca padrão Value.Metadata:

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

Os registros de metadados geralmente não são preservados quando um valor é usado com um operador ou função que cria 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"

As funções de biblioteca padrão Value.RemoveMetadata e Value.ReplaceMetadata podem ser usadas para remover todos os metadados de um valor e para substituir os metadados de um valor (em vez de mesclar os metadados em metadados possivelmente existentes).

O único operador que retorna os resultados que contêm metadados é o operador meta.

Operadores recursivos estruturalmente

Os valores podem ser cíclicos. Por exemplo:

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

O M manipula valores cíclicos mantendo o processo de construção de registros, listas e tabelas lento. Uma tentativa de criar um valor cíclico que não se beneficie de valores estruturados lentos que tenham sofrido intervenção gera 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 no M são definidos pela recursão estrutural. Por exemplo, a igualdade de listas e registros é definida pela igualdade conjunta de listas de itens e campos de registro 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 são percorridos repetidamente, mas o processo de recursão sempre é encerrado.

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

Operadores de seleção e de projeção

Os operadores de seleção e projeção permitem que os dados sejam extraídos dos valores de lista e de registro.

Acesso ao item

Um valor pode ser selecionado de uma lista ou tabela com base na respectiva posição de base zero nessa lista ou tabela usando uma expressão-de-acesso-a-item.

expressão-de-acesso-ao-item:
      seleção-de-item
      seleção-de-item-opcional
seleção-de-item:
      primary-expression
{item-selector}
seleção-de-item-opcional:
      primary-expression
{item-selector} ?
seletor-de-item:
      expressão

A expressão-de-acesso-a-itemx{y} retorna:

  • Para obter uma lista x e um número y, o item da lista x na posição y. O primeiro item de uma lista é considerado como tendo um índice ordinal igual a zero. Se a posição solicitada não existir na lista, um erro será gerado.

  • Para uma tabela x e um número y, a linha da tabela x na posição y. A primeira linha de uma tabela é considerada como tendo um índice ordinal igual a 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 do registro y para campos com nomes de campo equivalentes aos nomes de coluna 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-de-acesso-a-item também dá suporte ao formato x{y}?, que retorna null quando a posição (ou correspondência) y não existe na lista ou na tabela x. Se houver várias correspondências para y, 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 de tabela além daquela que está sendo acessada. Por exemplo:

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

Os seguintes preceitos são válidos quando o operador x{y} de acesso ao item é avaliado:

  • Erros gerados durante a avaliação das 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 de registro se x produz um valor de tabela e, caso contrário, produz um valor numérico.

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

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

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

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

Nenhum item em x diferente daquele na posição y é avaliado durante o processo de seleção de itens. (Para listas de streaming ou tabelas, os itens ou linhas que antecedem isso na posição y são ignorados, o que pode fazer com que eles sejam avaliados, dependendo da origem da lista ou da tabela.)

Acesso ao campo

A expressão-de-acesso-ao-campo é usada para selecionar um valor de um registro ou para projetar um registro ou uma tabela para um com menos campos ou colunas, respectivamente.

expressão-de-acesso-ao-campo:
      seleção-de-campo
      seleção-de-campo-de-destino-implícito
      projeção
      projeção-de-destino-implícito
seleção-de-campo:
      expressão-primária seletor-de-campo
seletor-de-campo:
      seletor-de-campo-obrigatório
      seletor-de-campo-opcional
seletor-de-campo-obrigatório:

      [field-name]
seletor-de-campo-opcional:
      [field-name] ?
nome-do-campo:
      identificador-generalizado
      identificador-entre-aspas
seleção-de-campo-de-destino-implícito:
      seletor-de-campo
projeção:
      expressão-primária projeção-obrigatória
      expressão-primária projeção-opcional
projeção-obrigatória:

      [required-selector-list]
projeção-opcional:
      [required-selector-list] ?
lista-de-seletores-obrigatórios:
      seletor-de-campo-obrigatório
      required-selector-list
,required-field-selector
projeção-de-destino-implícito:
      projeção-obrigatória
      projeção-opcional

A forma mais simples de acesso ao campo é a seleção de campo obrigatório. Ele usa o operador x[y] para procurar um campo em um registro por nome de campo. Se o campo y não existir em x, um erro será gerado. O formato x[y]? é usado para executar seleção de campo opcional e retorna null se o campo solicitado não existe 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 é compatível com os operadores para projeção de registro obrigatória e projeção de registro opcional. O operador x[[y1],[y2],...] projeta o registro em um novo registro com menos campos (selecionados por y1, y2 e ...). Se um campo selecionado não existir, um erro será gerado. O operador x[[y1],[y2],...]? projeta o registro para um novo registro com os campos selecionados por y1, y2 e ...; se um campo estiver ausente, null será usado em seu lugar. 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 formatos [y] e [y]? são compatíveis como uma referência abreviada ao identificador _ (sublinhado). As duas expressões a seguir são equivalentes:

[A]                 
_[A]

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

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

Os formatos [[y1],[y2],...] e [[y1],[y2],...]? também são compatíveis como uma abreviação e as duas expressões a seguir são, pela mesma lógica, equivalentes:

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

O formulário abreviado é particularmente útil em combinação com a abreviação each, uma maneira de introduzir uma função de um único parâmetro nomeado _ (para obter detalhes, confira declarações simplificadas). Juntas, as duas abreviações simplificam as 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 versão mais longa, que também parece de mais difícil compreensão:

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

O acesso ao campo não força a avaliação de campos além daqueles que estão sendo acessados. Por exemplo:

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

Os seguintes preceitos são válidos quando um operador x[y], x[y]?, x[[y]] ou x[[y]]? de acesso ao campo é avaliado:

  • Erros gerados 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 y e, em seguida, propagados. Qualquer acesso futuro ao campo y vai gerar o erro idêntico.

  • A expressão x produz um valor de registro ou de tabela ou resulta na geração de um erro.

  • Se o identificador y nomeia um campo que não existe em x, um erro com o código de motivo "Expression.Error" é gerado, a menos que o formato de operador opcional ...? seja usado; nesse caso, o valor null é retornado.

Nenhum campo de x exceto aquele 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:
      {1>unary-expression<1}
      unary-expression
metaunary-expression

O exemplo a seguir constrói um valor de texto com um registro de metadados usando o operador meta 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

Os seguintes preceitos são válidos ao aplicar o operador de combinação de metadados x meta y:

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

  • A expressão y precisa ser um registro, caso contrário, um erro com o código de motivo "Expression.Error" é gerado.

  • O registro de metadados resultante é o registro de metadados de x mesclado com y. (Para obter a semântica de mesclagem de registros, confira Mesclagem de registros.)

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

As funções de biblioteca padrão Value.RemoveMetadata e Value.ReplaceMetadata podem ser usadas para remover todos os metadados de um valor e para substituir os metadados de um valor (em vez de mesclar os 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.

expressão-de-igualdade:
      relational-expression
      relational-expression
=equality-expression
      relational-expression
<>equality-expression

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

Os seguintes preceitos são válidos ao aplicar os operadores de igualdade x = y e x <> y:

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

  • O operador = terá um resultado de true se os valores forem iguais; caso contrário, o resultado será false.

  • O operador <> terá um resultado de false se os valores forem iguais; caso contrário, o resultado será true.

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

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

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

  • Os seguintes preceitos são sempre verdadeiros:

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

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

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

    • Se um dos dois números for #nan, os números não serão iguais.

    • Quando nenhum dos números é #nan, eles 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 serão iguais se elas representarem o mesmo número de tiques de 100 nanossegundos.

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

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

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

  • Dois datetimezones serão iguais se os datetimes UTC correspondentes forem iguais. Para chegar ao datetime UTC correspondente, a diferença de horas/minutos é subtraída do componente datetime do datetimezone.

  • Dois valores de texto serão iguais se, ao usar uma comparação ordinal, com diferenciação de maiúsculas de minúsculas e sem diferenciação de cultura, eles tiverem o mesmo comprimento e caracteres iguais em posições correspondentes.

  • Dois valores de lista serão iguais se todas as condições a seguir forem verdadeiras:

    • As duas listas contêm o mesmo número de itens.

    • Os valores de cada item posicionalmente correspondente nas listas são iguais. Isso significa que não apenas as listas precisam conter itens iguais, os itens também 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 todas as seguintes condições forem verdadeiras:

    • 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 registro é igual ao campo com o mesmo nome presente no outro registro.

      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 serão iguais se todas as condições a seguir 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 em 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 maneira idêntica quando invocados.

    Dois valores de função fornecidos sempre terão 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 maneira idêntica quando consultados quanto à conformidade.

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

Operadores relacionais

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

expressão-relacional:
      additive-expression
      additive-expression
<relational-expression
      additive-expression
>relational-expression
      additive-expression
<=relational-expression
      additive-expression
>=relational-expression

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 Resultado
x < y true se x for menor que y, caso contrário, false
x > y true se x for maior que y, caso contrário, false
x <= y true se x for menor ou igual a y, caso contrário, false
x >= y true se x for maior ou igual a y, caso contrário, false

Por exemplo:

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

Os seguintes preceitos são válidos ao avaliar uma expressão que contém os operadores relacionais:

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

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

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

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

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

  • Para comparar duas datas, devemos comparar suas partes de ano; se forem iguais, suas partes de mês e, se forem iguais, suas partes de dia.

  • Para comparar dois datetimes, devemos comparar suas partes de ano; se forem iguais, suas partes de mês; se forem iguais, suas partes de dia; se forem iguais, suas partes de hora; se forem iguais, suas partes de minuto e, se forem iguais, suas partes de segundo.

  • Para comparar dois datetimezones, devemos normalizá-los para UTC, subtraindo a diferença de hora/minuto e, em seguida, comparando seus componentes datetime.

  • Duas durações serão comparadas de acordo com o número total de tiques de 100 nanossegundos que eles representarem.

  • Duas lógicas são comparadas de modo que true é considerado maior que false.

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

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

    • Quando nenhum operando é #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 < +∞, em que mín e máx são os menores e maiores valores finitos positivos que podem ser representados. Os nomes para -∞ e +∞ na linguagem de fórmula M são -#infinity e #infinity.

      Os efeitos notáveis dessa ordenação são:

      • Zeros negativos e positivos são considerados iguais.

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

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

  • Dois textos são comparados usando uma comparação ordinal de caractere por caractere, que diferencia maiúsculas de minúsculas e que não diferencia a cultura.

  • Para comparar duas horas, devemos comparar suas partes de hora; se forem iguais, suas partes de minuto e, se forem iguais, suas partes de segundo.

Operadores lógicos condicionais

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

expressão-OR-lógica:
      logical-and-expression
logical-and-expression
orlogical-or-expression
expressão-AND-lógica:
      expressão-is
      is-expression
andlogical-and-expression

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

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

As tabelas da verdade para os operadores or e and são mostradas abaixo, com o resultado da avaliação da expressão de 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

Os seguintes preceitos são válidos ao avaliar uma expressão que contém operadores lógicos condicionais:

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

  • Os operadores lógicos condicionais são definidos sobre os tipos logical e null. Se os valores de operando não forem desses tipos, um erro com o código de motivo "Expression.Error" 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 for avaliada como true.

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

As duas últimas propriedades dão aos operadores lógicos condicionais a respectiva qualificação "condicional". Essas propriedades também são conhecidas 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-de-adição:
      multiplicative-expression
      additive-expression
+multiplicative-expression
      additive-expression
-multiplicative-expression
expressão-multiplicadora:
      expressão-de-metadados
      multiplicative-expression
*metadata-expression
      multiplicative-expression
/metadata-expression

Precision

Os números em M são armazenados usando uma variedade de representações para manter o máximo possível de informações sobre números provenientes de uma variedade de fontes. Os números são convertidos apenas de uma representação para outra, conforme requerido pelos operadores aplicados a eles. Duas precisões são compatíveis com o M:

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

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

Os operadores aritméticos internos (+, -, * e /) usam precisão dupla. As funções de biblioteca padrão (Value.Add, Value.Subtract, Value.Multiply e 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 magnitudes grandes demais para serem representados.

  • Nenhum fluxo negativo numérico é possível: 0 e -0 representam valores de magnitudes pequenas demais para serem representados.

  • O valor especial do IEEE 754 #nan (NaN – não é um número) é usado para cobrir casos que não são matematicamente válidos, como uma divisão de zero por zero.

  • A conversão de precisão decimal para dupla é executada por meio do arredondamento de números decimais para o valor duplo equivalente mais próximo.

  • A conversão da precisão de dupla para decimal é executada por meio do arredondamento de números duplos para o valor decimal equivalente mais próximo e, se necessário, estourando para valores #infinity ou -#infinity.

Operador de adição

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

x a Resultado 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 magnitudes
type duration null null
null type duration null
typedatetime type duration typedatetime Deslocamento de data/hora por duração
type duration typedatetime typedatetime
typedatetime null null
null typedatetime null

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

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

Os erros gerados ao avaliar qualquer um dos dois operandos são propagados.

Soma numérica

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

Por exemplo:

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

O operador de adição + usado em números usa precisão dupla. A função de biblioteca padrão Value.Add pode ser usada para especificar a precisão decimal. Os seguintes preceitos são válidos ao computar uma soma de números:

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

    + a +0 -0 +∞ -∞ NaN
    x z x x +∞ -∞ NaN
    +0 a +0 +0 +∞ -∞ NaN
    -0 a +0 -0 +∞ -∞ NaN
    +∞ +∞ +∞ +∞ +∞ NaN NaN
    -∞ -∞ -∞ -∞ NaN -∞ NaN
    NaN NaN NaN NaN NaN NaN NaN
  • A soma em precisão decimal é computada sem perda de precisão. A escala do resultado é maior que as 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 tiques de 100 nanossegundos representada pelas durações. Por exemplo:

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

Deslocamento de data/hora por duração

Um datetimex e uma duração y podem ser adicionados usando x + y para computar um novo datetime cuja distância de x em uma linha do tempo linear é exatamente a magnitude de y. Aqui, datetime representa qualquer uma das opções Date, DateTime, DateTimeZone e Time; assim, um resultado não nulo será do mesmo tipo. A diferença de datetime por duração pode ser calculado da seguinte maneira:

  • Se o valor de dias desde o início da época de datetime for especificado, crie um datetime com os seguintes elementos de informação:

    • Calcule um novo equivalente de dias desde o início da época, a fim de dividir a magnitude de y pelo número de tiques de 100 nanossegundos em um período de 24 horas, truncando a parte decimal do resultado e adicionando esse valor aos dias desde o início da época de x.

    • Calcule uma nova contagem de tiques desde a meia-noite equivalente à adição da magnitude de y aos tiques desde a meia-noite de x, módulo o número de tiques de 100 nanossegundos em um período de 24 horas. Se x não especificar um valor para tiques desde a meia-noite, um valor de 0 será assumido.

    • Copie o valor da diferença em minutos em relação ao UTC, inalterado, de x.

  • Se o valor de dias desde o início da época de datetime não for especificado, crie um datetime com os seguintes elementos de informação especificados:

    • Calcule uma nova contagem de tiques desde a meia-noite equivalente à adição da magnitude de y aos tiques desde a meia-noite de x, módulo o número de tiques de 100 nanossegundos em um período de 24 horas. Se x não especificar um valor para tiques desde a meia-noite, um valor de 0 será assumido.

    • Copie os valores de dias desde o início da época e a diferença em minutos em relação ao UTC, inalterados, de x.

Os exemplos a seguir mostram o cálculo da soma temporal absoluta quando o datetime especifica os dias desde o início da é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 da diferença de datetime por duração para uma determinada hora:

#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 e y avaliadas, da seguinte maneira:

x Y Resultado 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
typedatetime typedatetime type duration Duração entre datetimes
typedatetime type duration typedatetime Deslocamento de Datetime por duração negada
typedatetime null null
null typedatetime null

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

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

Os erros gerados ao avaliar qualquer um dos dois operandos são propagados.

Diferença numérica

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

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

O operador de subtração - usado em números usa precisão dupla. A função de biblioteca padrão Value.Subtract pode ser usada para especificar a precisão decimal. Os seguintes preceitos são válidos ao computar uma diferença de números:

  • A diferença em precisão dupla é computada de acordo com as regras de aritmética de IEEE 754 de precisão dupla binária de 64 bits, IEEE 754-2008. A tabela a seguir lista os resultados de todas as combinações possíveis de valores finitos diferentes de zero, zeros, infinitos e NaNs. Na tabela, x e y são valores finitos diferentes de zero e z é o resultado de x - y. Se x e y forem iguais, z será zero positivo. Se x - y for grande demais para ser representado no tipo de destino, z será um infinito com o mesmo sinal que x - y.

    - a +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 em precisão decimal é computada sem perda de precisão. A escala do resultado é maior que as escalas dos dois operandos.

Diferença de durações

A diferença entre duas durações é a duração que representa a diferença entre o número de tiques de 100 nanossegundos representada pelas durações. Por exemplo:

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

Deslocamento de Datetime por duração negada

Um datetimex e uma duração y podem ser subtraídos usando x - y para computar um novo datetime. Aqui, datetime representa qualquer um entre date, datetime, datetimezone ou time. O datetime resultante tem uma distância de x em uma linha do tempo linear, que é exatamente a magnitude de y, na direção oposta ao sinal de y. A subtração de durações positivas gera resultados que são regressivos no tempo em relação a x, enquanto a subtração de valores negativos gera resultados que são progressivos 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 dois datetimes

Dois datetimest e u podem ser subtraídos usando t - u para computar a duração entre eles. Aqui, datetime representa qualquer um entre date, datetime, datetimezone ou time. A duração produzida subtraindo u de t precisa resultar t quando adicionada 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

A subtração t - u quando u > t resulta em uma duração negativa:

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

Os seguintes preceitos são válidos ao subtrair dois 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 x e y avaliadas, da seguinte maneira:

X Y Resultado 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últiplo da duração
type number type duration type duration Múltiplo da duração
type duration null null
null type duration null

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

Os erros gerados ao avaliar qualquer um dos dois operandos são propagados.

Produto numérico

O produto de dois números é computado 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 * usado em números usa precisão dupla. A função de biblioteca padrão Value.Multiply pode ser usada para especificar a precisão decimal. Os seguintes preceitos são válidos ao computar um produto de números:

  • O produto em precisão dupla é computado de acordo com as regras de aritmética de IEEE 754 de precisão dupla binária de 64 bits, IEEE 754-2008. A tabela a seguir lista os resultados de todas as combinações possíveis de valores finitos diferentes de zero, zeros, infinitos e NaNs. Na tabela, x e y são valores positivos finitos. z é o resultado de x * y. Se o resultado é grande demais para o tipo de destino, z é infinito. Se o resultado é pequeno demais 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 é computado sem perda de precisão. A escala do resultado é maior que as 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 tiques de 100 nanossegundos representado pela multiplicação do operando de duração pelo 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 e y avaliadas, da seguinte maneira:

X Y Resultado 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 uma 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 daquelas listadas na tabela, um erro com o código de motivo "Expression.Error" é gerado. Cada uma das combinações é abordada nas seções a seguir.

Os erros gerados ao avaliar qualquer um dos dois operandos são propagados.

Quociente numérico

O quociente de dois números é computado 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 / usado em números usa precisão dupla. A função de biblioteca padrão Value.Divide pode ser usada para especificar a precisão decimal. Os seguintes preceitos são válidos ao calcular um quociente de números:

  • O quociente em precisão dupla é computado de acordo com as regras de aritmética de IEEE 754 de precisão dupla binária de 64 bits, IEEE 754-2008. A tabela a seguir lista os resultados de todas as combinações possíveis de valores finitos diferentes de zero, zeros, infinitos e NaNs. Na tabela, x e y são valores positivos finitos. z é o resultado de x / y. Se o resultado é grande demais para o tipo de destino, z é infinito. Se o resultado é pequeno demais 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 é computada sem perda de precisão. A escala do resultado é maior que as 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 tiques de 100 nanossegundos representada 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 tiques de 100 nanossegundos representados pela duração x e o número y. Por exemplo:

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

Combinação de estrutura

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

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

Concatenação

Dois textos, duas listas ou dois valores de tabela podem ser concatenados usando x & y.

Este exemplo ilustra a concatenação de valores de texto:

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

Este exemplo ilustra a concatenação de listas:

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

Os seguintes preceitos são válidos ao concatenar dois valores usando x & y:

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

  • Nenhum erro será propagado se um item de x ou de y contiver um erro.

  • O resultado da concatenação de dois valores de texto é um valor de texto que contém o valor de x seguido imediatamente 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 seguidos por todos os itens de y.

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

Mesclar

Mesclagem de registros

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

Os exemplos a seguir ilustram a mesclagem de registros:

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

Os seguintes preceitos são válidos ao mesclar dois registros usando x + y:

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

  • Se um campo aparecer tanto em x quanto em y, o valor de y será usado.

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

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

  • Nenhum erro é gerado devido a um campo conter um erro.

  • O resultado é um registro.

Mesclagem de data e hora

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

O exemplo a seguir ilustra a mesclagem de uma data e uma hora:

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

Os seguintes preceitos são válidos ao mesclar dois registros usando x + y:

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

  • O resultado é um datetime.

Operadores unários

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

expressão-unária:
      expressão-de-tipo

      +expressão unária
      -expressão unária
      notexpressão unária

Operador de adição de unário

O operador de adição de unário (+x) é definido para os seguintes tipos de valores:

X Resultado Interpretação
type number type number Adição de unário
type duration type duration Adição de unário
null nulo

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

O operador de adição de unário permite que um sinal de + seja aplicado a um valor numérico, datetime ou nulo. O resultado é esse mesmo valor. Por exemplo:

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

Os seguintes preceitos são válidos ao avaliar o operador de adição de unário +x:

  • Os erros gerados ao avaliar x são propagados.

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

Operador de subtração de unário

O operador de subtração de unário (-x) é definido para os seguintes tipos de valores:

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

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

O operador de subtração de unário é 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)

Os seguintes preceitos são válidos ao avaliar o operador de subtração unário -x:

  • Os erros gerados ao avaliar 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 um NaN, o resultado também será um NaN.

Operador de negação lógica

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

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

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

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

Os seguintes preceitos são válidos ao avaliar o operador lógico de negação not x:

  • Os erros gerados ao avaliar x são propagados.

  • O valor produzido da avaliação da expressão x precisa ser um valor lógico, caso contrário, um erro com o código de motivo "Expression.Error" precisará 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 operadores de tipo.

Operador de compatibilidade de tipo

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

X Y Resultado
type any tipo-primitivo-que-permite-valor-nulo type logical

A expressão x is y retornará true se o tipo atribuído de x for compatível com y e retornará false se o tipo atribuído de x for incompatível com y. y precisa ser um tipo-primitivo-que-permite-valor-nulo.

expressão-is:
      expressão-as
      is-expression
isnullable-primitive-type
tipo-primitivo-que-permite-valor-nulo:

      nullableopcional tipo-primitivo

A compatibilidade de tipo, conforme compatível com o operador is, é um subconjunto de compatibilidade de tipo geral e é definida usando as seguintes regras:

  • Se x for nulo, ele será compatível se y for do tipo any, do tipo null ou de um tipo anulável.

  • Se x for não nulo, ele será compatível se o tipo primitivo de x for o mesmo que y.

Os seguintes preceitos são válidos ao avaliar a expressão x is y:

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

Operador de asserção de tipo

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

X Y Resultado
type any tipo-primitivo-que-permite-valor-nulo type any

A expressão x as y declara que o valor x é compatível com y, conforme o operador is. Se não for compatível, um erro será gerado. y precisa ser um tipo-primitivo-que-permite-valor-nulo.

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

A expressão x as y é avaliada desta maneira:

  • Uma verificação de compatibilidade de tipo x is y é executada e a asserção retorna x inalterado se o teste é executado com sucesso.

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

Exemplos:

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

Os seguintes preceitos são válidos ao avaliar a expressão x as y:

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

Operador de união

O operador de união ?? retornará o resultado do operando esquerdo dele caso ele não seja nulo; do contrário, ele retornará o resultado do operando direito. O operando direito será avaliado se e somente se o operando esquerdo for nulo.