Valores

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

Variante Literal
Nulo null
Lógica true    false
Número 0    1    -1    1.5    2.3e-5
Tempo #time(09,15,00)
Date #date(2013,02,26)
DateTime #datetime(2013,02,26, 09,15,00)
DateTimeZone #datetimezone(2013,02,26, 09,15,00, 09,00)
Duração #duration(0,1,30,0)
Texto "hello"
Binário #binary("AQID")
Lista {1, 2, 3}
Registo [ 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 cobrem cada tipo de valor em detalhes. Os tipos e a atribuição de tipos 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 dão exemplos. A definição completa da semântica do operador segue em Operadores.

Nulo

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

Operador Result
x > y Maior que
x >= y Maior ou igual a
x < y Menor que
x <= y Menor ou igual a
x = y Igual
x <> y Não é igual a
x ?? y Coalesce

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

Lógico

Um valor lógico é usado para operações booleanas 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 Result
x > y Maior que
x >= y Maior ou igual a
x < y Menor que
x <= y Menor ou igual a
x = y Igual
x <> y Não é igual a
x or y Lógica condicional OU
x ?? y Coalesce
x and y Lógica condicional E
not x Lógico NÃO

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

Número

Um valor numérico é usado para operações numéricas e aritméticas. Seguem-se exemplos de literais numéricos:

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 pelo menos a precisão de um Duplo (mas pode reter mais precisão). A representação dupla é congruente com o padrão de precisão dupla IEEE de 64 bits para aritmética binária de ponto flutuante definido em [IEEE 754-2008]. (O A representação dupla tem um intervalo dinâmico aproximado de 5,0 x 10324 a 1,7 x 10308 com uma precisão de 15-16 dígitos.)

Os seguintes valores especiais também são considerados valores numéricos :

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

  • Infinito positivo (#infinity) e infinito negativo (-#infinity). As infinidades são produzidas 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 Not-a-Number (#nan), muitas vezes abreviado NaN. NaNs são produzidos por operações de ponto flutuante inválidas, como dividir zero por zero.

Operações matemáticas binárias são realizadas usando uma precisão. A precisão determina o domínio para o qual os operandos são arredondados e o domínio no qual a operação é executada. Na ausência de uma precisão explicitamente especificada, tais operações são realizadas utilizando uma 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 torna-se 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 torna-se infinito positivo ou infinito negativo.

  • Se uma operação matemática é inválida, o resultado da operação torna-se NaN.

  • Se um ou ambos os operandos de uma operação de ponto flutuante for NaN, o resultado da operação torna-se NaN.

Os seguintes operadores são definidos para valores numéricos:

Operador Result
x > y Maior que
x >= y Maior ou igual a
x < y Menor que
x <= y Menor ou igual a
x = y Igual
x <> y Não é igual a
x + y Soma
x - y Diferença
x * y Produto
x / y Quociente
x ?? y Coalesce
+x Unário mais
-x Negação

O tipo nativo de valores numéricos é o tipo numberintrínseco.

Hora

Um valor de tempo armazena uma representação opaca da hora do dia. Um tempo é codificado como o número de ticks desde a meia-noite, que conta o número de ticks de 100 nanossegundos que decorreram em um relógio de 24 horas. O número máximo de carrapatos desde a meia-noite corresponde às 23:59:59.9999999 horas.

Embora não haja sintaxe literal para tempos, várias funções de biblioteca padrão são fornecidas para construí-los. Os tempos também podem ser construídos usando a função #timeintrínseca:

#time(hour, minute, second)

O seguinte deve ser mantido ou um erro com o código Expression.Error de razão é gerado:

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

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

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

Operador Result
x = y Igual
x <> y Não é igual a
x >= y Maior ou igual a
x > y Maior que
x < y Menor que
x <= y Menor ou igual a
x ?? y Coalesce

Os operadores a seguir permitem que um ou ambos os seus operandos sejam uma data:

Operador Operando esquerdo Operando direito Significado
x + y time duration Data compensada pela duração
x + y duration time Data compensada pela duração
x - y time duration Data compensada pela duração negada
x - y time time Duração entre datas
x & y date time Data/hora mesclada

O tipo nativo de valores de tempo é o tipo timeintrínseco.

Date

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 Era Comum no calendário gregoriano. O número máximo de dias desde a época é 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. As datas também podem ser construídas usando a função #dateintrínseca:

#date(year, month, day)

O seguinte deve ser mantido ou um erro com o código Expression.Error de razão é 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 ano escolhidos.

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

Operador Result
x = y Igual
x <> y Não é igual a
x >= y Maior ou igual a
x > y Maior que
x < y Menor que
x <= y Menor ou igual a
x ?? y Coalesce

Os operadores a seguir permitem que um ou ambos os seus operandos sejam uma data:

Operador Operando esquerdo Operando direito Significado
x + y date duration Data compensada pela duração
x + y duration date Data compensada pela duração
x - y date duration Data compensada pela duração negada
x - y date date Duração entre datas
x & y date time Data/hora mesclada

O tipo nativo de valores de data é o tipo dateintrínseco .

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. As datas/hora também podem ser construídas utilizando a função #datetimeintrínseca:

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

O seguinte deve manter ou um erro com o código de razão Expression.Error é 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 ano escolhidos.

Os seguintes operadores são definidos para valores datetime:

Operador Result
x = y Igual
x <> y Não é igual a
x >= y Maior ou igual a
x > y Maior que
x < y Menor que
x <= y Menor ou igual a
x ?? y Coalesce

Os operadores a seguir permitem que um ou ambos os seus operandos sejam data/hora:

Operador Operando esquerdo Operando direito Significado
x + y datetime duration Data/hora deslocada por duração
x + y duration datetime Data/hora deslocada por duração
x - y datetime duration Data/hora compensada pela duração negada
x - y datetime datetime Duração entre datetimes

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

DateTimeZone

Um valor datetimezone contém um datetime e um fuso horário. Um fuso horário é codificado como um número de minutos de deslocamento do UTC, que conta o número de minutos que a parte de tempo do datetime deve ser deslocada do Universal Coordinated Time (UTC). O número mínimo de minutos de deslocamento do UTC é -840, representando um deslocamento UTC de -14:00, ou quatorze horas antes do UTC. O número máximo de minutos de deslocamento do UTC é 840, correspondendo a um deslocamento 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í-los. Os fusos data/hora também podem ser construídos utilizando a função #datetimezoneintrínseca :

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

O seguinte deve ser mantido ou um erro com o código Expression.Error de razão é gerado:

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

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

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

Operador Result
x = y Igual
x <> y Não é igual a
x >= y Maior ou igual a
x > y Maior que
x < y Menor que
x <= y Menor ou igual a
x ?? y Coalesce

Os operadores a seguir permitem que um ou ambos os seus operandos sejam um fuso datetime:

Operador Operando esquerdo Operando direito Significado
x + y datetimezone duration Deslocamento de fuso horário de data por duração
x + y duration datetimezone Deslocamento de fuso horário de data por duração
x - y datetimezone duration Fuso horário de data compensado pela duração negada
x - y datetimezone datetimezone Duração entre fusos data-hora

O tipo nativo de valores de fuso data/hora é o tipo datetimezoneintrínseco.

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 ticks de 100 nanossegundos. A magnitude de uma duração pode ser positiva ou negativa, com valores positivos denotando progresso para frente no tempo e valores negativos denotando progresso para trás no tempo. O valor mínimo que pode ser armazenado em uma duração é -9,223,372,036,854,775,808 ticks, ou 10,675,199 dias 2 horas 48 minutos 05,4775808 segundos para trás no tempo. O valor máximo que pode ser armazenado em uma duração é 9,223,372,036,854,775,807 ticks, ou 10,675,199 dias 2 horas 48 minutos 05,4775807 segundos para frente 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. As durações também podem ser construídas usando a função #durationintrínseca:

#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 Result
x = y Igual
x <> y Não é igual a
x >= y Maior ou igual a
x > y Maior que
x < y Menor que
x <= y Menor ou igual a
x ?? y Coalesce

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

Operador Operando esquerdo Operando direito Significado
x + y datetime duration Data/hora deslocada por duração
x + y duration datetime Data/hora deslocada por duração
x + y duration duration Soma das durações
x - y datetime duration Data/hora compensada pela 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 durationintrínseco .

Texto

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

_text literal:
      " texto-literal-caracteresopt "
texto-literal-caracteres:
      texto-literal-caractere texto-literal-caracteresopt
texto-literal-caractere:
      caractere de texto único
      caractere-fuga-sequência
      seqüência de fuga de aspas duplas
caractere de texto único:

      Qualquer caractere, exceto " (U+0022) ou # (U+0023) seguido de ( (U+0028)
seqüência de fuga de aspas duplas:
      "" (U+0022, U+0022)

Segue-se um exemplo de um valor de texto :

"ABC" // the text value ABC

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

Operador Result
x = y Igual
x <> y Não é igual a
x >= y Maior ou igual a
x > y Maior que
x < y Menor que
x <= y Menor ou igual a
x & y Concatenação
x ?? y Coalesce

O tipo nativo de valores de texto é o tipo textintrínseco .

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í-los. Valores binários também podem ser construídos usando a função #binaryintrínseca .

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 Result
x = y Igual
x <> y Não é igual a
x >= y Maior ou igual a
x > y Maior que
x < y Menor que
x <= y Menor ou igual a
x ?? y Coalesce

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

Listagem

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-lista:
      { item-listopt }
lista de itens:
      item
      
,lista de itens
artigo:
      expressão
      expressão de expressão
..

Segue-se um exemplo de 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 da lista e o valor "C" é o último item da lista.

  • Os itens de uma lista não são avaliados até que sejam acessados.
  • Enquanto os valores de lista construídos usando a sintaxe de lista produzirão itens na ordem em que 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 cada vez que são enumerados.

Para incluir uma sequência de números inteiros numa lista, o a..b formulário pode ser utilizado:

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

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

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

Uma lista pode efetivamente ter um número infinito de itens; List.Count para tais listas é indefinido e pode gerar um erro ou não terminar.

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

{}  // empty list

Os seguintes operadores são definidos para listas:

Operador Result
x = y Igual
x <> y Não é igual a
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 listintrínseco , que especifica um tipo de item de any.

Registo

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

record-expressão:
      [ opt pela listade campos ]
lista de campos:
      campo
      lista de campos
,
domínio:
      expressão de nome
= de campo
nome do campo:
      identificador generalizado
      identificador cotado

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

[ x = 1, y = 2 ]

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

[ a = [ b = 2 ] ]

O seguinte vale 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 produz um valor quando avaliado, esse se torna o valor do campo do registro resultante.

  • Se a expressão atribuída a um nome de campo gera um erro quando avaliada, o fato de que um erro foi gerado é registrado com o campo junto com o valor de erro que foi gerado. O acesso subsequente a esse campo fará com que um erro seja gerado novamente com o valor de erro registrado.

  • A expressão é avaliada em um ambiente como o ambiente pai somente com variáveis mescladas que correspondem ao valor de cada campo do registro, exceto o 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 do inicializador do registro.

  • Cada nome de campo especificado deve ser exclusivo dentro do registro ou é um erro. Os nomes são comparados usando 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 registos 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 Record.FieldCount função. 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 a partir de uma lista de valores e uma lista de nomes de campos ou um tipo de registro. Por exemplo:

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

O acima exposto é equivalente a:

[ a = 1, b = 2 ]

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

Operador Result
x = y Igual
x <> y Não é igual a
x & y Unir
x ?? y Coalesce

Os exemplos a seguir ilustram os 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 nos nomes dos campos.

[ 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 recordintrínseco , que especifica uma lista vazia aberta de campos.

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 da tabela, os nomes das colunas da tabela, os tipos de 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. As tabelas também podem ser construídas usando a função #tableintrínseca .

O exemplo a seguir constrói uma tabela a partir de uma lista de nomes de colunas e uma lista de linhas. A tabela resultante conterá duas colunas e type any 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 da tabela tem um tipo de tabela que especifica nomes e tipos de coluna.

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

Operador Result
x = y Igual
x <> y Não é igual a
x & y Concatenação
x ?? y Coalesce

A concatenação de tabela alinha colunas com nomes semelhantes e preenche colunas null que aparecem em apenas uma das tabelas de operando. O exemplo a seguir 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 tableintrínseco) que lista os nomes das colunas, especifica todos os tipos de coluna como sendo quaisquer e não tem chaves. (Ir para Tipos de tabela para obter detalhes sobre tipos de tabela.)

Function

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

Type

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