Partilhar via


Values

Um valor é um dado produzido pela avaliação de uma expressão. Esta secçã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
Null null
Logical true    false
Number 0    1    -1    1.5    2.3e-5
Time #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)
Duration #duration(0,1,30,0)
Text "hello"
Binary #binary("AQID")
List {1, 2, 3}
Record [ A = 1, B = 2 ]
Table #table({"X","Y"},{{0,1},{1,0}})
Function (x) => x + 1
Type type { number }    type table [ A = any, B = text ]

As secções seguintes abordam cada tipo de valor em detalhe. Os tipos e a atribuição de tipos são definidos formalmente em Tipos. Os valores das funções são definidos em Funções. As secções seguintes listam os operadores definidos para cada tipo de valor e dão exemplos. A definição completa de semântica de operadores segue-se em Operadores.

Null

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:

Operator Result
x > y Maior que
x >= y Maior ou igual
x < y Menos de
x <= y Menor ou igual
x = y Equal
x <> y Não é igual
x ?? y Coalesce

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

Logical

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

Operator Result
x > y Maior que
x >= y Maior ou igual
x < y Menos de
x <= y Menor ou igual
x = y Equal
x <> y Não é igual
x or y OR lógico condicional
x ?? y Coalesce
x and y Lógica condicional AND
not x Lógico NÃO

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

Number

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 manter mais precisão). A representação dupla é congruente com o padrão IEEE de dupla precisão de 64 bits para aritmética binária em ponto flutuante definido em [IEEE 754-2008]. (A representação dupla tem uma gama dinâmica aproximada de 5,0 x10 324 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, zero positivo e zero negativo comportam-se de forma 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 tais como dividir um número diferente de zero por zero. Por exemplo, 1.0 / 0.0 resulta em infinito positivo, e -1.0 / 0.0 em menos infinito.

  • O valor Não-um-Número (#nan), frequentemente abreviado como NaN. NaNs são produzidos por operações de ponto flutuante inválidas, como dividir zero por zero.

As 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 em que a operação é realizada. Na ausência de uma precisão explicitamente especificada, tais operações são realizadas usando Precisão Dupla.

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

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

  • Se uma operação matemática for 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:

Operator Result
x > y Maior que
x >= y Maior ou igual
x < y Menos de
x <= y Menor ou igual
x = y Equal
x <> y Não é igual
x + y Sum
x - y Difference
x * y Product
x / y Quotient
x ?? y Coalesce
+x Unário mais
-x Negation

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

Time

Um valor temporal armazena uma representação opaca da 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 que decorreram num relógio de 24 horas. O número máximo de tiques desde a meia-noite corresponde às 23:59:59.9999999 horas.

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

#time(hour, minute, second)

O seguinte deve ser confirmado ou será apresentado um erro com código Expression.Error de razão:

0 ≤ horas ≤ 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:

Operator Result
x = y Equal
x <> y Não é igual
x >= y Maior ou igual
x > y Maior que
x < y Menos de
x <= y Menor ou igual
x ?? y Coalesce

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

Operator Operando Esquerdo Operando Direito Meaning
x + y time duration Data compensada pela duração
x + y duration time Data compensada pela duração
x - y time duration Data deslocada pela duração anulada
x - y time time Duração entre datas
x & y date time Data e hora fundida

O tipo nativo dos valores temporais é 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, começando em 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 exista sintaxe literal para datas, são fornecidas várias funções padrão de biblioteca para as construir. As datas também podem ser construídas usando a função #dateintrínseca :

#date(year, month, day)

O seguinte deve ser confirmado ou será apresentado um erro com código Expression.Error de razão:

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:

Operator Result
x = y Equal
x <> y Não é igual
x >= y Maior ou igual
x > y Maior que
x < y Menos de
x <= y Menor ou igual
x ?? y Coalesce

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

Operator Operando Esquerdo Operando Direito Meaning
x + y date duration Data compensada pela duração
x + y duration date Data compensada pela duração
x - y date duration Data deslocada pela duração anulada
x - y date date Duração entre datas
x & y date time Data e hora fundida

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

DateTime

Um valor de data-hora contém tanto uma data como uma hora.

Embora não exista uma sintaxe literal para datas-hora, são fornecidas várias funções padrão de biblioteca para as construir. Os tempos de data também podem ser construídos usando a função #datetimeintrínseca :

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

O seguinte deve ser verificado ou um erro com código de razão Expressão. O erro é levantado: 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 de data-hora:

Operator Result
x = y Equal
x <> y Não é igual
x >= y Maior ou igual
x > y Maior que
x < y Menos de
x <= y Menor ou igual
x ?? y Coalesce

Os seguintes operadores permitem que um ou ambos os seus operandos sejam data-hora:

Operator Operando Esquerdo Operando Direito Meaning
x + y datetime duration Hora de data compensada pela duração
x + y duration datetime Hora de data compensada pela duração
x - y datetime duration Hora de data compensada pela duração anulada
x - y datetime datetime Duração entre datas

O tipo nativo dos valores data-hora é o tipo datetimeintrínseco .

DateTimeZone

Um valor de data-hora contém uma data-hora e um fuso horário. Um fuso horário é codificado como um número de minutos deslocado em relação ao UTC, que conta o número de minutos em que a parte horária da data-hora deve ser deslocada do Tempo Coordenado Universal (UTC). O número mínimo de minutos de deslocamento em relação ao UTC é -840, representando um deslocamento do UTC de -14:00, ou catorze horas antes do UTC. O número máximo de minutos de deslocamento em relação ao UTC é de 840, correspondendo a um deslocamento de UTC de 14:00.

Embora não exista uma sintaxe literal para os zones-data-hora, são fornecidas várias funções padrão da biblioteca para os construir. Os fusos data-hora também podem ser construídos usando a função #datetimezoneintrínseca :

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

O seguinte deve ser confirmado ou será apresentado um erro com código Expression.Error de razão:

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

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

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

Operator Result
x = y Equal
x <> y Não é igual
x >= y Maior ou igual
x > y Maior que
x < y Menos de
x <= y Menor ou igual
x ?? y Coalesce

Os seguintes operadores permitem que um ou ambos os seus operandos sejam um fuso de data-hora:

Operator Operando Esquerdo Operando Direito Meaning
x + y datetimezone duration Zone-data-hora desajustado pela duração
x + y duration datetimezone Zone-data-hora desajustado pela duração
x - y datetimezone duration Data-hora deslocado pela duração anulada
x - y datetimezone datetimezone Duração entre fusos data-horários

O tipo nativo dos valores de data-hora é o tipo datetimezoneintrínseco .

Duration

Um valor de duração armazena uma representação opaca da distância entre dois pontos numa linha temporal medida em ticks de 100 nanossegundos. A magnitude de uma duração pode ser positiva ou negativa, com valores positivos a indicar progresso no tempo e valores negativos a indicar progresso para trás no tempo. O valor mínimo que pode ser armazenado numa 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 numa duração é de 9.223.372.036.854.775.807 ticks, ou 10.675.199 dias 2 horas 48 minutos 05,4775807 segundos para o futuro.

Embora não exista uma sintaxe literal para as durações, são fornecidas várias funções padrão de biblioteca para as construir. 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 nos valores de duração:

Operator Result
x = y Equal
x <> y Não é igual
x >= y Maior ou igual
x > y Maior que
x < y Menos de
x <= y Menor ou igual
x ?? y Coalesce

Adicionalmente, os seguintes operadores permitem que um ou ambos os seus operandos tenham um valor de duração:

Operator Operando Esquerdo Operando Direito Meaning
x + y datetime duration Hora de data compensada pela duração
x + y duration datetime Hora de data compensada pela duração
x + y duration duration Soma das durações
x - y datetime duration Hora de data compensada pela duração anulada
x - y datetime datetime Duração entre datas
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
x / y duration duration Quociente numérico de durações

O tipo nativo dos valores de duração é o tipo durationintrínseco .

Text

Um valor de texto representa uma sequência de caracteres Unicode. Os valores do texto têm uma forma literal conforme à seguinte gramática:

_text-literal:
       " caracteres literaisde texto optam"
caracteres literais de texto:
      texto-literal-caracteres-texto-literal-caracteresoptam
text-literal-character:
      single-text-character
      character-escape-sequence
      double-quote-escape-sequence
carácter de texto único:

      Qualquer carácter exceto () ou # (U+0023) seguido de ( (U+0028)U+0022"
double-quote-escape-sequence:
       "" (U+0022, U+0022)

Segue-se um exemplo de valor de texto :

"ABC" // the text value ABC

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

Operator Result
x = y Equal
x <> y Não é igual
x >= y Maior ou igual
x > y Maior que
x < y Menos de
x <= y Menor ou igual
x & y Concatenation
x ?? y Coalesce

O tipo nativo dos valores do texto é o tipo textintrínseco .

Binary

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

Embora não exista uma sintaxe literal para valores binários, são fornecidas várias funções padrão de biblioteca para os construir. Valores binários também podem ser construídos usando a função #binaryintrínseca .

O exemplo seguinte 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 :

Operator Result
x = y Equal
x <> y Não é igual
x >= y Maior ou igual
x > y Maior que
x < y Menos de
x <= y Menor ou igual
x ?? y Coalesce

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

List

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 forma:

list-expression:
      { item-listopt }
Lista de itens:
      item
      Lista de itens
,
item:
      expressão
      
.. Expressão

Segue-se um exemplo de 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é serem acedidos.
  • Embora os valores de lista construídos usando a sintaxe da lista produzam itens pela ordem em que aparecem na lista de itens, em geral, listas devolvidas de funções de biblioteca podem produzir um conjunto diferente ou um número diferente de valores cada vez que são enumeradas.

Para incluir uma sequência de números inteiros numa lista, pode ser usada a a..b forma:

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

O número de itens numa 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, na prática, 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, chama-se lista vazia. Uma lista vazia é escrita como:

{}  // empty list

Os seguintes operadores são definidos para listas:

Operator Result
x = y Equal
x <> y Não é igual
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 dos valores de lista é o tipo listintrínseco , que especifica um tipo de item de any.

Record

Um valor de registo é uma sequência ordenada de campos. Um campo consiste num nome de campo, que é um valor de texto que identifica de forma única o campo dentro do registo, e num valor de campo. O valor do campo pode ser qualquer tipo de valor, incluindo registo. Os registos podem ser construídos usando a sintaxe de inicialização, da seguinte forma:

record-expression:
       [ Lista de campos opt]
Lista de campo:
      campo
      Lista de campos
,
field:
      Expressão por nomes
=de campo
field-name:
      generalized-identifier
      identificador citado

O exemplo seguinte constrói um registo com um corpo nomeado x com valor 1, e um corpo nomeado y com valor 2.

[ x = 1, y = 2 ]

O exemplo seguinte constrói um registo com a campo nomeado a com um valor de registo aninhado. O registo aninhado tem um campo nomeado b com valor 2.

[ a = [ b = 2 ] ]

O seguinte verifica-se ao avaliar uma expressão de registo:

  • 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 avaliado, então esse torna-se o valor do campo do registo resultante.

  • Se a expressão atribuída a um nome de campo gerar um erro quando avaliada, então o facto de um erro ter sido levantado é registado com o campo juntamente com o valor do erro que foi levantado. O acesso subsequente a esse campo fará com que um erro seja novamente lançado com o valor de erro registado.

  • A expressão é avaliada num ambiente como o ambiente pai apenas com variáveis fundidas que correspondem ao valor de todos os campos do registo, exceto aquele que está a ser inicializado.

  • Um valor num registo não é avaliado até que o campo correspondente seja acedido.

  • Um valor num registo é avaliado no máximo uma vez.

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

  • A ordem dos campos dentro do registo é definida pela ordem em que aparecem na expressão-inicializador-registo.

  • Cada nome de campo especificado deve ser único dentro do registo, caso contrário é um erro. Os nomes são comparados através de uma comparação ordinal.

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

Um registo sem campos é chamado de registo vazio, e é escrito da seguinte forma:

[] // empty record

Embora a ordem dos campos de um registo não seja significativa ao aceder a um campo ou comparar dois registos, é significativa noutros contextos, como quando os campos de um registo 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 num registo pode ser determinado usando a Record.FieldCount função. Por exemplo:

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

Para além de usar a sintaxe [ ]de inicialização de registos, os registos podem ser construídos a partir de uma lista de valores e de uma lista de nomes de campos ou de um tipo de registo. Por exemplo:

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

O acima é equivalente a:

[ a = 1, b = 2 ]

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

Operator Result
x = y Equal
x <> y Não é igual
x & y Merge
x ?? y Coalesce

Os exemplos seguintes ilustram os operadores acima. Note que a fusão de registos usa os campos do operando direito para sobrescrever campos do operando esquerdo, caso haja 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 dos valores de registo é o tipo recordintrínseco , que especifica uma lista aberta e vazia de campos.

Table

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 das colunas da tabela e a estrutura das chaves da tabela (se existirem).

Embora não exista uma sintaxe literal para as tabelas, são fornecidas várias funções padrão de biblioteca para as construir. As tabelas também podem ser construídas usando a função #tableintrínseca .

O exemplo seguinte constrói uma tabela a partir de uma lista de nomes de colunas 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 pode também ser usado para especificar um tipo de tabela completo:

#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 colunas.

Os seguintes operadores são definidos para os valores das tabelas:

Operator Result
x = y Equal
x <> y Não é igual
x & y Concatenation
x ?? y Coalesce

A concatenação de tabelas alinha colunas com nomes semelhantes e preenche null colunas que aparecem apenas numa das tabelas de operandos. O exemplo seguinte 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 dos valores de tabela é um tipo de tabela personalizado (derivado do tipo tableintrínseco) que lista os nomes das colunas, especifica todos os tipos de colunas como quaisquer e não tem chaves. (Consulte Tipos de Tabela para detalhes sobre os tipos de tabelas.)

Function

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

Tipo

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