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.
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 null
intrínseco.
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 logical
intrínseco .
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 number
intrínseco.
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 #time
intrí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 time
intrínseco.
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 #date
intrí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 date
intrínseco .
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 #datetime
intrí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 datetime
intrínseco .
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 #datetimezone
intrí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 datetimezone
intrínseco.
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 #duration
intrí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 duration
intrínseco .
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 text
intrínseco .
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 #binary
intrí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.
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 list
intrínseco , que especifica um tipo de item de any
.
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 1
e 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 record
intrínseco , que especifica uma lista vazia aberta de campos.
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 #table
intrí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 table
intrí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.)
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.
Um valor de tipo é um valor que classifica outros valores. Os detalhes dos valores de tipo são descritos em Tipos.