Compartilhar via


Valores

Um valor são dados produzidos pela avaliação de uma expressão. Esta seção descreve os tipos de valores na linguagem M. Cada tipo de valor é associado a uma sintaxe literal, um conjunto de valores que são desse tipo, um conjunto de operadores definidos sobre esse conjunto de valores e um tipo intrínseco atribuído a valores recém-criados.

Tipo Literal
Nulo null
Lógico true    false
Número 0    1    -1    1.5    2.3e-5
Hora #time(09,15,00)
Data #date(2013,02,26)
DateTime #datetime(2013,02,26, 09,15,00)
DateTimeZone #datetimezone(2013,02,26, 09,15,00, 09,00)
Duration #duration(0,1,30,0)
Texto "hello"
Binary #binary("AQID")
Lista {1, 2, 3}
Registro [ A = 1, B = 2 ]
Tabela #table({"X","Y"},{{0,1},{1,0}})
Função (x) => x + 1
Tipo type { number }    type table [ A = any, B = text ]

As seções a seguir abordam cada tipo de valor em detalhes. Os tipos e a atribuição de tipo são definidos formalmente em Tipos. Os valores de função são definidos em Funções. As seções a seguir listam os operadores definidos para cada tipo de valor e fornecem exemplos. A definição completa de semântica de operadores é fornecida a seguir, em Operadores.

Nulo

Um valor nulo é usado para representar a ausência de um valor ou um valor de um estado indeterminado ou desconhecido. Um valor nulo é gravado usando o literal null. Os seguintes operadores são definidos para valores nulos:

Operador Resultado
x > y Maior que
x >= y Maior ou igual
x < y Menor que
x <= y Inferior ou igual
x = y Igual
x <> y Diferente
x ?? y Coalesce

O tipo nativo do valor null é o tipo intrínseco null.

Logical

Um valor lógico é usado para operações boolianas e tem o valor true ou false. Um valor lógico é escrito usando os literais true e false. Os seguintes operadores são definidos para valores lógicos:

Operador Resultado
x > y Maior que
x >= y Maior ou igual
x < y Menor que
x <= y Inferior ou igual
x = y Igual
x <> y Diferente
x or y OR lógico condicional
x ?? y Coalesce
x and y AND lógico condicional
not x NOT lógico

O tipo nativo de ambos os valores lógicos (true e false) é o tipo intrínseco logical.

Número

Um valor de número é usado para operações numéricas e aritméticas. Estes são exemplos de literais de número:

3.14  // Fractional number 
-1.5  // Fractional number 
1.0e3 // Fractional number with exponent
123   // Whole number 
1e3   // Whole number with exponent 
0xff  // Whole number in hex (255)

Um número é representado com, no mínimo, a precisão de um Double (mas pode reter mais precisão). A representação de Double é congruente com o padrão de precisão dupla de 64 bits do IEEE para aritmética de ponto flutuante binário definido em [IEEE 754-2008]. (A representação de Double tem um intervalo dinâmico aproximado de 5,0 x 10324 para 1,7 x 10308 com uma precisão de 15-16 dígitos.)

Os seguintes valores especiais também são considerados valores do tipo number:

  • Zero positivo e zero negativo. Na maioria das situações, zero positivo e zero negativo se comportam de maneira idêntica ao valor zero simples, mas certas operações distinguem entre os dois.

  • Infinito positivo (#infinity) e infinito negativo (-#infinity). Os infinitos são produzidos por operações como a divisão de um número diferente de zero por zero. Por exemplo, 1.0 / 0.0 produz infinito positivo e -1.0 / 0.0 produz infinito negativo.

  • O valor não é um número (#nan), geralmente abreviado como NaN. NaNs são produzidos por operações de ponto flutuante inválidas, como a divisão de zero por zero.

As operações matemáticas binárias são executadas usando uma precisão. A precisão determina o domínio no qual os operandos são arredondados e o domínio no qual a operação é executada. Na ausência de uma precisão especificada explicitamente, essas operações são executadas usando precisão dupla.

  • Se o resultado de uma operação matemática for muito pequeno para o formato de destino, o resultado da operação se tornará zero positivo ou zero negativo.

  • Se o resultado de uma operação matemática for muito grande para o formato de destino, o resultado da operação se tornará infinito positivo ou infinito negativo.

  • Se uma operação matemática for inválida, o resultado da operação se tornará NaN.

  • Se um ou ambos os operandos de uma operação de ponto flutuante forem NaN, o resultado da operação se tornará NaN.

Os seguintes operadores são definidos para valores de número:

Operador Resultado
x > y Maior que
x >= y Maior ou igual
x < y Menor que
x <= y Inferior ou igual
x = y Igual
x <> y Diferente
x + y Soma
x - y Diferença
x * y Produto
x / y Quociente
x ?? y Coalesce
+x Adição de unário
-x Negação

O tipo nativo de valores de número é o tipo intrínseco number.

Hora

Um valor temporal armazena uma representação opaca de hora do dia. Uma hora é codificada como o número de tiques desde a meia-noite, que conta o número de tiques de 100 nanossegundos decorridos em um relógio de 24 horas. O número máximo de tiques desde a meia-noite corresponde a 23:59:59,9999999 horas.

Embora não haja sintaxe literal para valores temporais, várias funções de biblioteca padrão são fornecidas para construí-las. Também é possível construir valores temporais usando a função intrínseca #time:

#time(hour, minute, second)

As seguintes condições precisarão ser compridas ou um erro com o código de motivo Expression.Error será gerado:

0 ≤ hora ≤ 24
0 ≤ minuto ≤ 59
0 ≤ segundo ≤ 59

Além disso, se hora = 24, então minuto e segundo precisam ser zero.

Os seguintes operadores são definidos para valores de tempo:

Operador Resultado
x = y Igual
x <> y Diferente
x >= y Maior ou igual
x > y Maior que
x < y Menor que
x <= y Inferior ou igual
x ?? y Coalesce

Os seguintes operadores permitem que um ou ambos os operandos sejam uma data:

Operador Operando Esquerdo Operando Direito Significado
x + y time duration Deslocamento de Date por duração
x + y duration time Deslocamento de Date por duração
x - y time duration Deslocamento de data por duração negada
x - y time time Duração entre datas
x & y date time Data/hora mescladas

O tipo nativo de valores de tempo é o tipo intrínseco time.

Data

Um valor de data armazena uma representação opaca de um dia específico. Uma data é codificada como um número de dias desde a época, a partir de 1º de janeiro de 0001 da Era Comum no calendário gregoriano. O número máximo de dias desde a época é de 3652058, correspondendo a 31 de dezembro de 9999.

Embora não haja sintaxe literal para datas, várias funções de biblioteca padrão são fornecidas para construí-las. Também é possível construir datas usando a função intrínseca #date:

#date(year, month, day)

As seguintes condições precisarão ser compridas ou um erro com o código de motivo Expression.Error será gerado:

1 ≤ ano ≤ 9999
1 ≤ mês ≤ 12
1 ≤ dia ≤ 31

Além disso, o dia deve ser válido para o mês e o ano escolhidos.

Os seguintes operadores são definidos para valores de data:

Operador Resultado
x = y Igual
x <> y Diferente
x >= y Maior ou igual
x > y Maior que
x < y Menor que
x <= y Inferior ou igual
x ?? y Coalesce

Os seguintes operadores permitem que um ou ambos os operandos sejam uma data:

Operador Operando Esquerdo Operando Direito Significado
x + y date duration Deslocamento de Date por duração
x + y duration date Deslocamento de Date por duração
x - y date duration Deslocamento de data por duração negada
x - y date date Duração entre datas
x & y date time Data/hora mescladas

O tipo nativo de valores de data é o tipo intrínseco date.

DateTime

Um valor datetime contém uma data e uma hora.

Embora não haja sintaxe literal para datetimes, várias funções de biblioteca padrão são fornecidas para construí-las. Também é possível construir datetimes usando a função intrínseca #datetime:

#datetime(year, month, day, hour, minute, second)

As seguintes condições precisarão ser compridas ou um erro com o código de motivo Expression.Error será gerado: 1 ≤ ano ≤ 9999
1 ≤ mês ≤ 12
1 ≤ dia ≤ 31
0 ≤ hora ≤ 23
0 ≤ minuto ≤ 59
0 ≤ segundo ≤ 59

Além disso, o dia deve ser válido para o mês e o ano escolhidos.

Os seguintes operadores são definidos para valores datetime:

Operador Resultado
x = y Igual
x <> y Diferente
x >= y Maior ou igual
x > y Maior que
x < y Menor que
x <= y Inferior ou igual
x ?? y Coalesce

Os seguintes operadores permitem que um ou ambos os operandos sejam um datetime:

Operador Operando Esquerdo Operando Direito Significado
x + y datetime duration Deslocamento de data/hora por duração
x + y duration datetime Deslocamento de data/hora por duração
x - y datetime duration Deslocamento de Datetime por duração negada
x - y datetime datetime Duração entre datetimes

O tipo nativo de valores datetime é o tipo intrínseco datetime.

DateTimeZone

Um valor de datetimezone contém um datetime e um timezone. Um timezone é codificado como um número de minutos de diferença UTC, que conta o número de minutos que datetime deverá ter de diferença em relação ao UTC (horário coordenado universal). O número mínimo de minutos de diferença UTC é -840, representando uma diferença UTC de -14:00 ou quatorze horas antes do UTC. O número máximo de minutos de diferença UTC é 840, correspondendo a uma diferença UTC de 14:00.

Embora não haja sintaxe literal para datetimezones, várias funções de biblioteca padrão são fornecidas para construí-las. Também é possível construir datetimezones usando a função intrínseca #datetimezone:

#datetimezone(
       year, month, day,
       hour, minute, second,
       offset-hours, offset-minutes)

As seguintes condições precisarão ser compridas ou um erro com o código de motivo Expression.Error será gerado:

1 ≤ ano ≤ 9999
1 ≤ mês ≤ 12
1 ≤ dia ≤ 31
0 ≤ hora ≤ 23
0 ≤ minuto ≤ 59
0 ≤ segundo ≤ 59
-14 ≤ horas de diferença ≤ 14
-59 ≤ minutos de diferença ≤ 59

Além disso, o dia precisa ser válido para o mês e o ano escolhidos e, se horas-de-diferença = 14, então minutos-de-diferença < = 0 e, se horas-de-diferença =-14, então minutos-de-diferença > = 0.

Os seguintes operadores são definidos para valores datetimezone:

Operador Resultado
x = y Igual
x <> y Diferente
x >= y Maior ou igual
x > y Maior que
x < y Menor que
x <= y Inferior ou igual
x ?? y Coalesce

Os seguintes operadores permitem que um ou ambos os operandos sejam um datetimezone:

Operador Operando Esquerdo Operando Direito Significado
x + y datetimezone duration Deslocamento DateTimeZone por duração
x + y duration datetimezone Deslocamento DateTimeZone por duração
x - y datetimezone duration Deslocamento de datetimezone por duração negada
x - y datetimezone datetimezone Duração entre datetimezones

O tipo nativo de valores datetimezone é o tipo intrínseco datetimezone.

Duração

Um valor de duração armazena uma representação opaca da distância entre dois pontos em uma linha do tempo medida em tiques de 100 nanossegundos. A magnitude de uma duração pode ser positiva ou negativa, em que valores positivos indicam avanço no tempo e valores negativos indicam retrocesso no tempo. O valor mínimo que pode ser armazenado em uma duração é de -9.223.372.036.854.775.808 tiques ou 10.675.199 dias, 2 horas, 48 minutos e 5,4775808 segundos recuando no tempo. O valor máximo que pode ser armazenado em uma duração é de -9.223.372.036.854.775.807 tiques ou 10.675.199 dias, 2 horas, 48 minutos e 5,4775807 segundos avançando no tempo.

Embora não haja sintaxe literal para durações, várias funções de biblioteca padrão são fornecidas para construí-las. Também é possível construir durações usando a função intrínseca #duration:

#duration(0, 0, 0, 5.5)          // 5.5 seconds 
#duration(0, 0, 0, -5.5)         // -5.5 seconds 
#duration(0, 0, 5, 30)           // 5.5 minutes 
#duration(0, 0, 5, -30)          // 4.5 minutes 
#duration(0, 24, 0, 0)           // 1 day 
#duration(1, 0, 0, 0)            // 1 day

Os seguintes operadores são definidos em valores de duração:

Operador Resultado
x = y Igual
x <> y Diferente
x >= y Maior ou igual
x > y Maior que
x < y Menor que
x <= y Inferior ou igual
x ?? y Coalesce

Além disso, os seguintes operadores permitem que um ou ambos os operandos sejam um valor de duração:

Operador Operando Esquerdo Operando Direito Significado
x + y datetime duration Deslocamento de data/hora por duração
x + y duration datetime Deslocamento de data/hora por duração
x + y duration duration Soma das durações
x - y datetime duration Deslocamento de Datetime por duração negada
x - y datetime datetime Duração entre datetimes
x - y duration duration Diferença de durações
x * y duration number N vezes uma duração
x * y number duration N vezes uma duração
x / y duration number Fração de uma duração

O tipo nativo de valores de duração é o tipo intrínseco duration.

Texto

Um valor de texto representa uma sequência de caracteres Unicode. Os valores de texto têm um formato literal em conformidade com a seguinte gramática:

_literal-de-texto:
      " caracteresliterais de texto optam "
caracteres-de-literal-de-texto:
      caractere-de-literal-de-texto caracteres-de-literal-de-textoopcional
caractere-de-literal-de-texto:
      caractere-de-texto-individual
      sequência-de-escape-de-caracteres
      sequência-de-escape-com-aspas-duplas
caractere-de-texto-individual:

      Qualquer caractere, exceto " (U+0022) ou # (U+0023) seguido por ( (U+0028)
sequência-de-escape-com-aspas-duplas:
      "" (U+0022, U+0022)

Segue um exemplo de um valor de texto:

"ABC" // the text value ABC

Os seguintes operadores são definidos em valores de texto:

Operador Resultado
x = y Igual
x <> y Diferente
x >= y Maior ou igual
x > y Maior que
x < y Menor que
x <= y Inferior ou igual
x & y Concatenação
x ?? y Coalesce

O tipo nativo de valores de texto é o tipo intrínseco text.

Binário

Um valor binário representa uma sequência de bytes.

Embora não haja sintaxe literal para valores binários, várias funções de biblioteca padrão são fornecidas para construí-las. Também é possível construir valores binários usando a função intrínseca #binary.

O exemplo a seguir constrói um valor binário a partir de uma lista de bytes:

#binary( {0x00, 0x01, 0x02, 0x03} )

Os seguintes operadores são definidos em valores binários:

Operador Resultado
x = y Igual
x <> y Diferente
x >= y Maior ou igual
x > y Maior que
x < y Menor que
x <= y Inferior ou igual
x ?? y Coalesce

O tipo nativo de valores binários é o tipo intrínseco binary.

Lista

Um valor de lista é um valor que produz uma sequência de valores quando enumerado. Um valor produzido por uma lista pode conter qualquer tipo de valor, incluindo uma lista. As listas podem ser construídas usando a sintaxe de inicialização, da seguinte maneira:

expressão-de-lista:
      { lista-de-itensopcional }
lista-de-itens:
      item
      lista de itens de itens
,
item:
      expressão
      expressão
.. expressão

Veja o seguinte exemplo, que mostra uma expressão-de-lista que define uma lista com três valores de texto: "A", "B" e "C".

{"A", "B", "C"}

O valor "A" é o primeiro item na lista e o valor "C" é o último item da lista.

  • Os itens de uma lista não são avaliados até que sejam acessados.
  • Embora os valores de lista construídos usando a sintaxe de lista produzam itens na ordem em que eles aparecem na lista-de-itens, em geral, as listas retornadas de funções de biblioteca podem produzir um conjunto diferente ou um número diferente de valores sempre que são enumeradas.

Para incluir uma sequência de números inteiros em uma lista, o formato a..b pode ser usado:

{ 1, 5..9, 11 }     // { 1, 5, 6, 7, 8, 9, 11 }

O número de itens em uma lista, conhecido como a contagem da lista, pode ser determinado usando a função List.Count.

List.Count({true, false})  // 2 
List.Count({})             // 0

Uma lista pode ter efetivamente um número infinito de itens; a List.Count para essas listas é indefinida e pode gerar um erro ou não ter fim.

Se uma lista não contiver nenhum item, ela será chamada de lista vazia. Uma lista vazia é escrita como:

{}  // empty list

Os seguintes operadores são definidos para listas:

Operador Resultado
x = y Igual
x <> y Diferente
x & y Concatenate
x ?? y Coalesce

Por exemplo:

{1, 2} & {3, 4, 5}   // {1, 2, 3, 4, 5} 
{1, 2} = {1, 2}      // true 
{2, 1} <> {1, 2}     // true

O tipo nativo de valores de lista é o tipo intrínseco list, que especifica um tipo de item de any.

Record

Um valor de registro é uma sequência ordenada de campos. Um campo consiste em um nome do campo (um valor de texto que identifica o campo de maneira exclusiva dentro do registro) e em um valor do campo. O valor do campo pode ser qualquer tipo de valor, incluindo um registro. Registros podem ser construídos usando sintaxe de inicialização, da seguinte maneira:

expressão-de-registro:
      [ opção de listade campos ]
lista-de-campos:
      field
      campo
, lista de campos
campo:
      expressão de nome
= de campo
nome-do-campo:
      identificador-generalizado
      identificador-entre-aspas

O exemplo a seguir constrói um registro com um campo chamado x com o valor 1 e um campo chamado y com o valor 2.

[ x = 1, y = 2 ]

O exemplo a seguir constrói um registro com um campo a chamado a com um valor de registro aninhado. O registro aninhado tem um campo chamado b com o valor 2.

[ a = [ b = 2 ] ]

Os seguintes preceitos são válidos ao avaliar uma expressão de registro:

  • A expressão atribuída a cada nome de campo é usada para determinar o valor do campo associado.

  • Se a expressão atribuída a um nome de campo produzir um valor quando avaliada, esse se tornará o valor do campo do registro resultante.

  • Se a expressão atribuída a um nome de campo gerar um erro quando for avaliada, o fato de um erro ter sido gerado será registrado com o campo junto com o valor de erro que tiver sido gerado. O acesso subsequente a esse campo fará com que um erro seja recriado com o valor de erro registrado.

  • A expressão é avaliada em um ambiente como o ambiente pai somente com variáveis mescladas, no sentido de que correspondem ao valor de todos os campos do registro, exceto por aquele que está sendo inicializado.

  • Um valor em um registro não é avaliado até que o campo correspondente seja acessado.

  • Um valor em um registro é avaliado no máximo uma vez.

  • O resultado da expressão é um valor de registro com um registro de metadados vazio.

  • A ordem dos campos dentro do registro é definida pela ordem em que eles aparecem na expressão-inicializadora-do-registro.

  • Cada nome de campo especificado precisa ser exclusivo dentro do registro, caso contrário resulta em um erro. Os nomes são comparados pelo uso de uma comparação ordinal.

    [ x = 1, x = 2 ] // error: field names must be unique 
    [ X = 1, x = 2 ] // OK

Um registro sem campos é chamado de registro vazio e é escrito da seguinte maneira:

[] // empty record

Embora a ordem dos campos de um registro não seja significativa ao acessar um campo ou comparar dois registros, ela é significativa em outros contextos, como quando os campos de um registro são enumerados.

Os mesmos dois registros produzem resultados diferentes quando os campos são obtidos:

Record.FieldNames([ x = 1, y = 2 ]) // [ "x", "y" ] 
Record.FieldNames([ y = 1, x = 2 ]) // [ "y", "x" ]

O número de campos em um registro pode ser determinado usando a função Record.FieldCount. Por exemplo:

Record.FieldCount([ x = 1, y = 2 })  // 2 
Record.FieldCount([])                // 0

Além de usar a sintaxe de inicialização de registro [ ], os registros podem ser construídos com base em uma lista de valores e uma lista de nomes de campo ou um tipo de registro. Por exemplo:

Record.FromList({1, 2}, {"a", "b"})

O exemplo acima é equivalente a:

[ a = 1, b = 2 ]

Os seguintes operadores são definidos para valores de registro:

Operador Resultado
x = y Igual
x <> y Diferente
x & y Mesclar
x ?? y Coalesce

Os exemplos a seguir ilustram o uso dos operadores acima. Observe que a mesclagem de registros usa os campos do operando direito para substituir campos do operando esquerdo, caso haja uma sobreposição em nomes de campo.

[ a = 1, b = 2 ] & [ c = 3 ]    // [ a = 1, b = 2, c = 3 ] 
[ a = 1, b = 2 ] & [ a = 3 ]    // [ a = 3, b = 2 ] 
[ a = 1, b = 2 ] = [ b = 2, a = 1 ]         // true 
[ a = 1, b = 2, c = 3 ] <> [ a = 1, b = 2 ] // true

O tipo nativo de valores de registro é o tipo intrínseco record, que especifica uma lista de campos vazia aberta.

Tabela

Um valor de tabela é uma sequência ordenada de linhas. Uma linha é uma sequência ordenada de valores de coluna. O tipo da tabela determina o comprimento de todas as linhas na tabela, os nomes das colunas da tabela, os tipos das colunas da tabela e a estrutura das chaves da tabela (se houver).

Embora não haja sintaxe literal para tabelas, várias funções de biblioteca padrão são fornecidas para construí-las. Também é possível construir tabelas usando a função intrínseca #table.

O exemplo a seguir constrói uma tabela a partir de uma lista de nomes de coluna e uma lista de linhas. A tabela resultante conterá duas colunas de type any e três linhas.

#table({"x", "x^2"}, {{1,1}, {2,4}, {3,9}})

#table também pode ser usado para especificar um tipo de tabela completa:

#table(
    type table [Digit = number, Name = text],  
    {{1,"one"}, {2,"two"}, {3,"three"}} 
    )

Aqui, o novo valor de tabela tem um tipo de tabela que especifica os nomes de coluna e os tipos de coluna.

Os seguintes operadores são definidos para valores de tabela:

Operador Resultado
x = y Igual
x <> y Diferente
x & y Concatenação
x ?? y Coalesce

A concatenação de tabelas alinha colunas com nomes semelhantes e preenche null para colunas que aparecem em apenas uma das tabelas de operandos. Este exemplo ilustra a concatenação de tabelas:

  #table({"A","B"}, {{1,2}}) 
& #table({"B","C"}, {{3,4}})
A B C
1 2 null
null 3 4

O tipo nativo de valores de tabela é um tipo de tabela personalizado (derivado do tipo intrínseco table) que lista os nomes de coluna, especifica todos os tipos de coluna como any e não tem nenhuma chave. (Acesse Tipos de tabela para obter detalhes sobre os tipos de tabela.)

Função

Um valor de função é um valor que mapeia um conjunto de argumentos para apenas um valor. Os detalhes dos valores de função são descritos em Funções.

Tipo

Um valor de tipo é um valor que classifica outros valores. Os detalhes dos valores de tipo são descritos em Tipos.