Values
A value is data produced by evaluating an expression. This section describes the kinds of values in the M language. Each kind of value is associated with a literal syntax, a set of values that are of that kind, a set of operators defined over that set of values, and an intrinsic type ascribed to newly constructed values.
Kind | 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 ] |
The following sections cover each value kind in detail. Types and type ascription are defined formally in Types. Function values are defined in Functions. The following sections list the operators defined for each value kind and give examples. The full definition of operator semantics follows in Operators.
Null
A null value is used to represent the absence of a value, or a value of indeterminate or unknown state. A null value is written using the literal null
. The following operators are defined for null values:
Operator | Result |
---|---|
x > y |
Greater than |
x >= y |
Greater than or equal |
x < y |
Less than |
x <= y |
Less than or equal |
x = y |
Equal |
x <> y |
Not equal |
x ?? y |
Coalesce |
The native type of the null
value is the intrinsic type null
.
Logical
A logical value is used for Boolean operations has the value true or false. A logical value is written using the literals true
and false
. The following operators are defined for logical values:
Operator | Result |
---|---|
x > y |
Greater than |
x >= y |
Greater than or equal |
x < y |
Less than |
x <= y |
Less than or equal |
x = y |
Equal |
x <> y |
Not equal |
x or y |
Conditional logical OR |
x ?? y |
Coalesce |
x and y |
Conditional logical AND |
not x |
Logical NOT |
The native type of both logical values (true
and false
) is the intrinsic type logical
.
Number
A number value is used for numeric and arithmetic operations. The following are examples of number literals:
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)
A number is represented with at least the precision of a Double (but may retain more precision). The Double representation is congruent with the IEEE 64-bit double precision standard for binary floating point arithmetic defined in [IEEE 754-2008]. (The Double representation have an approximate dynamic range from 5.0 x 10324 to 1.7 x 10308 with a precision of 15-16 digits.)
The following special values are also considered to be number values:
Positive zero and negative zero. In most situations, positive zero and negative zero behave identically as the simple value zero, but certain operations distinguish between the two.
Positive infinity (
#infinity
) and negative infinity (-#infinity
). Infinities are produced by such operations as dividing a non-zero number by zero. For example,1.0 / 0.0
yields positive infinity, and-1.0 / 0.0
yields negative infinity.The Not-a-Number value (
#nan
), often abbreviated NaN. NaNs are produced by invalid floating-point operations, such as dividing zero by zero.
Binary mathematical operations are performed using a Precision. The precision determines the domain to which the operands are rounded and the domain in which the operation is performed. In the absence of an explicitly specified precision, such operations are performed using Double Precision.
If the result of a mathematical operation is too small for the destination format, the result of the operation becomes positive zero or negative zero.
If the result of a mathematical operation is too large for the destination format, the result of the operation becomes positive infinity or negative infinity.
If a mathematical operation is invalid, the result of the operation becomes NaN.
If one or both operands of a floating-point operation is NaN, the result of the operation becomes NaN.
The following operators are defined for number values:
Operator | Result |
---|---|
x > y |
Greater than |
x >= y |
Greater than or equal |
x < y |
Less than |
x <= y |
Less than or equal |
x = y |
Equal |
x <> y |
Not equal |
x + y |
Sum |
x - y |
Difference |
x * y |
Product |
x / y |
Quotient |
x ?? y |
Coalesce |
+x |
Unary plus |
-x |
Negation |
The native type of number values is the intrinsic type number
.
Time
A time value stores an opaque representation of time of day. A time is encoded as the number of ticks since midnight, which counts the number of 100-nanosecond ticks that have elapsed on a 24-hour clock. The maximum number of ticks since midnight corresponds to 23:59:59.9999999 hours.
Although there is no literal syntax for times, several standard library functions are provided to construct them. Times may also be constructed using the intrinsic function #time
:
#time(hour, minute, second)
The following must hold or an error with reason code Expression.Error
is raised:
0 ≤ hour ≤ 24
0 ≤ minute ≤ 59
0 ≤ second ≤ 59
In addition, if hour = 24, then minute and second must be zero.
The following operators are defined for time values:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x >= y |
Greater than or equal |
x > y |
Greater than |
x < y |
Less than |
x <= y |
Less than or equal |
x ?? y |
Coalesce |
The following operators permit one or both of their operands to be a date:
Operator | Left Operand | Right Operand | Meaning |
---|---|---|---|
x + y |
time |
duration |
Date offset by duration |
x + y |
duration |
time |
Date offset by duration |
x - y |
time |
duration |
Date offset by negated duration |
x - y |
time |
time |
Duration between dates |
x & y |
date |
time |
Merged datetime |
The native type of time values is the intrinsic type time
.
Date
A date value stores an opaque representation of a specific day. A date is encoded as a number of days since epoch, starting from January 1, 0001 Common Era on the Gregorian calendar. The maximum number of days since epoch is 3652058, corresponding to December 31, 9999.
Although there is no literal syntax for dates, several standard library functions are provided to construct them. Dates may also be constructed using the intrinsic function #date
:
#date(year, month, day)
The following must hold or an error with reason code Expression.Error
is raised:
1 ≤ year ≤ 9999
1 ≤ month ≤ 12
1 ≤ day ≤ 31
In addition, the day must be valid for the chosen month and year.
The following operators are defined for date values:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x >= y |
Greater than or equal |
x > y |
Greater than |
x < y |
Less than |
x <= y |
Less than or equal |
x ?? y |
Coalesce |
The following operators permit one or both of their operands to be a date:
Operator | Left Operand | Right Operand | Meaning |
---|---|---|---|
x + y |
date |
duration |
Date offset by duration |
x + y |
duration |
date |
Date offset by duration |
x - y |
date |
duration |
Date offset by negated duration |
x - y |
date |
date |
Duration between dates |
x & y |
date |
time |
Merged datetime |
The native type of date values is the intrinsic type date
.
DateTime
A datetime value contains both a date and time.
Although there is no literal syntax for datetimes, several standard library functions are provided to construct them. Datetimes may also be constructed using the intrinsic function #datetime
:
#datetime(year, month, day, hour, minute, second)
The following must hold or an error with reason code Expression.Error is raised:
1 ≤ year ≤ 9999
1 ≤ month ≤ 12
1 ≤ day ≤ 31
0 ≤ hour ≤ 23
0 ≤ minute ≤ 59
0 ≤ second ≤ 59
In addition, the day must be valid for the chosen month and year.
The following operators are defined for datetime values:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x >= y |
Greater than or equal |
x > y |
Greater than |
x < y |
Less than |
x <= y |
Less than or equal |
x ?? y |
Coalesce |
The following operators permit one or both of their operands to be a datetime:
Operator | Left Operand | Right Operand | Meaning |
---|---|---|---|
x + y |
datetime |
duration |
Datetime offset by duration |
x + y |
duration |
datetime |
Datetime offset by duration |
x - y |
datetime |
duration |
Datetime offset by negated duration |
x - y |
datetime |
datetime |
Duration between datetimes |
The native type of datetime values is the intrinsic type datetime
.
DateTimeZone
A datetimezone value contains a datetime and a timezone. A timezone is encoded as a number of minutes offset from UTC, which counts the number of minutes the time portion of the datetime should be offset from Universal Coordinated Time (UTC). The minimum number of minutes offset from UTC is -840, representing a UTC offset of -14:00, or fourteen hours earlier than UTC. The maximum number of minutes offset from UTC is 840, corresponding to a UTC offset of 14:00.
Although there is no literal syntax for datetimezones, several standard library functions are provided to construct them. Datetimezones may also be constructed using the intrinsic function #datetimezone
:
#datetimezone(
year, month, day,
hour, minute, second,
offset-hours, offset-minutes)
The following must hold or an error with reason code Expression.Error
is raised:
1 ≤ year ≤ 9999
1 ≤ month ≤ 12
1 ≤ day ≤ 31
0 ≤ hour ≤ 23
0 ≤ minute ≤ 59
0 ≤ second ≤ 59
-14 ≤ offset-hours ≤ 14
-59 ≤ offset-minutes ≤ 59
In addition, the day must be valid for the chosen month and year and, if offset-hours = 14, then offset-minutes <= 0 and, if offset-hours = -14, then offset-minutes >= 0.
The following operators are defined for datetimezone values:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x >= y |
Greater than or equal |
x > y |
Greater than |
x < y |
Less than |
x <= y |
Less than or equal |
x ?? y |
Coalesce |
The following operators permit one or both of their operands to be a datetimezone:
Operator | Left Operand | Right Operand | Meaning |
---|---|---|---|
x + y |
datetimezone |
duration |
Datetimezone offset by duration |
x + y |
duration |
datetimezone |
Datetimezone offset by duration |
x - y |
datetimezone |
duration |
Datetimezone offset by negated duration |
x - y |
datetimezone |
datetimezone |
Duration between datetimezones |
The native type of datetimezone values is the intrinsic type datetimezone
.
Duration
A duration value stores an opaque representation of the distance between two points on a timeline measured 100-nanosecond ticks. The magnitude of a duration can be either positive or negative, with positive values denoting progress forwards in time and negative values denoting progress backwards in time. The minimum value that can be stored in a duration is -9,223,372,036,854,775,808 ticks, or 10,675,199 days 2 hours 48 minutes 05.4775808 seconds backwards in time. The maximum value that can be stored in a duration is 9,223,372,036,854,775,807 ticks, or 10,675,199 days 2 hours 48 minutes 05.4775807 seconds forwards in time.
Although there is no literal syntax for durations, several standard library functions are provided to construct them. Durations may also be constructed using the intrinsic function #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
The following operators are defined on duration values:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x >= y |
Greater than or equal |
x > y |
Greater than |
x < y |
Less than |
x <= y |
Less than or equal |
x ?? y |
Coalesce |
Additionally, the following operators allow one or both of their operands to be a duration value:
Operator | Left Operand | Right Operand | Meaning |
---|---|---|---|
x + y |
datetime |
duration |
Datetime offset by duration |
x + y |
duration |
datetime |
Datetime offset by duration |
x + y |
duration |
duration |
Sum of durations |
x - y |
datetime |
duration |
Datetime offset by negated duration |
x - y |
datetime |
datetime |
Duration between datetimes |
x - y |
duration |
duration |
Difference of durations |
x * y |
duration |
number |
N times a duration |
x * y |
number |
duration |
N times a duration |
x / y |
duration |
number |
Fraction of a duration |
The native type of duration values is the intrinsic type duration
.
Text
A text value represents a sequence of Unicode characters. Text values have a literal form conformant to the following grammar:
_text-literal:
"
text-literal-charactersopt "
text-literal-characters:
text-literal-character text-literal-charactersopt
text-literal-character:
single-text-character
character-escape-sequence
double-quote-escape-sequence
single-text-character:
Any character except "
(U+0022
) or #
(U+0023
) followed by (
(U+0028
)
double-quote-escape-sequence:
""
(U+0022
, U+0022
)
The following is an example of a text value:
"ABC" // the text value ABC
The following operators are defined on text values:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x >= y |
Greater than or equal |
x > y |
Greater than |
x < y |
Less than |
x <= y |
Less than or equal |
x & y |
Concatenation |
x ?? y |
Coalesce |
The native type of text values is the intrinsic type text
.
Binary
A binary value represents a sequence of bytes.
Although there is no literal syntax for binary values, several standard library functions are provided to construct them. Binary values may also be constructed using the intrinsic function #binary
.
The following example constructs a binary value from a list of bytes:
#binary( {0x00, 0x01, 0x02, 0x03} )
The following operators are defined on binary values:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x >= y |
Greater than or equal |
x > y |
Greater than |
x < y |
Less than |
x <= y |
Less than or equal |
x ?? y |
Coalesce |
The native type of binary values is the intrinsic type binary.
List
A list value is a value which produces a sequence of values when enumerated. A value produced by a list can contain any kind of value, including a list. Lists can be constructed using the initialization syntax, as follows:
list-expression:
{ item-listopt }
item-list:
item
item ,
item-list
item:
expression
expression ..
expression
The following is an example of a list-expression that defines a list with three text values: "A"
, "B"
, and "C"
.
{"A", "B", "C"}
The value "A"
is the first item in the list, and the value "C"
is the last item in the list.
- The items of a list are not evaluated until they are accessed.
- While list values constructed using the list syntax will produce items in the order they appear in item-list, in general, lists returned from library functions may produce a different set or a different number of values each time they are enumerated.
To include a sequence of whole number in a list, the a..b
form can be used:
{ 1, 5..9, 11 } // { 1, 5, 6, 7, 8, 9, 11 }
The number of items in a list, known as the list count, can be determined using the List.Count
function.
List.Count({true, false}) // 2
List.Count({}) // 0
A list may effectively have an infinite number of items; List.Count
for such lists is undefined and may either raise an error or not terminate.
If a list contains no items, it is called an empty list. An empty list is written as:
{} // empty list
The following operators are defined for lists:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x & y |
Concatenate |
x ?? y |
Coalesce |
For example:
{1, 2} & {3, 4, 5} // {1, 2, 3, 4, 5}
{1, 2} = {1, 2} // true
{2, 1} <> {1, 2} // true
The native type of list values is the intrinsic type list
, which specifies an item type of any
.
Record
A record value is an ordered sequence of fields. A field consists of a field name, which is a text value that uniquely identifies the field within the record, and a field value. The field value can be any kind of value, including record. Records can be constructed using initialization syntax, as follows:
record-expression:
[
field-listopt ]
field-list:
field
field ,
field-list
field:
field-name =
expression
field-name:
generalized-identifier
quoted-identifier
The following example constructs a record with a field named x
with value 1
, and a field named y
with value 2
.
[ x = 1, y = 2 ]
The following example constructs a record with a
field named a with a nested record value. The nested record has a field named b
with value 2
.
[ a = [ b = 2 ] ]
The following holds when evaluating a record expression:
The expression assigned to each field name is used to determine the value of the associated field.
If the expression assigned to a field name produces a value when evaluated, then that becomes the value of the field of the resulting record.
If the expression assigned to a field name raises an error when evaluated, then the fact that an error was raised is recorded with the field along with the error value that was raised. Subsequent access to that field will cause an error to be re-raised with the recorded error value.
The expression is evaluated in an environment like the parent environment only with variables merged in that correspond to the value of every field of the record, except the one being initialized.
A value in a record is not evaluated until the corresponding field is accessed.
A value in a record is evaluated at most once.
The result of the expression is a record value with an empty metadata record.
The order of the fields within the record is defined by the order that they appear in the record-initializer-expression.
Every field name that is specified must be unique within the record, or it is an error. Names are compared using an ordinal comparison.
[ x = 1, x = 2 ] // error: field names must be unique
[ X = 1, x = 2 ] // OK
A record with no fields is called an empty record, and is written as follows:
[] // empty record
Although the order of the fields of a record is not significant when accessing a field or comparing two records, it is significant in other contexts such as when the fields of a record are enumerated.
The same two records produce different results when the fields are obtained:
Record.FieldNames([ x = 1, y = 2 ]) // [ "x", "y" ]
Record.FieldNames([ y = 1, x = 2 ]) // [ "y", "x" ]
The number of fields in a record can be determined using the Record.FieldCount
function. For example:
Record.FieldCount([ x = 1, y = 2 }) // 2
Record.FieldCount([]) // 0
In addition to using the record initialization syntax [ ]
, records can be constructed from a list of values, and a list of field names or a record type. For example:
Record.FromList({1, 2}, {"a", "b"})
The above is equivalent to:
[ a = 1, b = 2 ]
The following operators are defined for record values:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x & y |
Merge |
x ?? y |
Coalesce |
The following examples illustrate the above operators. Note that record merge uses the fields from the right operand to override fields from the left operand, should there be an overlap in field names.
[ 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
The native type of record values is the intrinsic type record
, which specifies an open empty list of fields.
Table
A table value is an ordered sequence of rows. A row is an ordered sequence of column values. The table's type determines the length of all rows in the table, the names of the table's columns, the types of the table's columns, and the structure of the table's keys (if any).
Although there is no literal syntax for tables, several standard library functions are provided to construct them. Tables may also be constructed using the intrinsic function #table
.
The following example constructs a table from a list of column names and a list of rows. The resulting table will contain two columns of type any
and three rows.
#table({"x", "x^2"}, {{1,1}, {2,4}, {3,9}})
#table
can also be used to specify a full table type:
#table(
type table [Digit = number, Name = text],
{{1,"one"}, {2,"two"}, {3,"three"}}
)
Here the new table value has a table type that specifies column names and column types.
The following operators are defined for table values:
Operator | Result |
---|---|
x = y |
Equal |
x <> y |
Not equal |
x & y |
Concatenation |
x ?? y |
Coalesce |
Table concatenation aligns like-named columns and fills in null
for columns appearing in only one of the operand tables. The following example illustrates table concatenation:
#table({"A","B"}, {{1,2}})
& #table({"B","C"}, {{3,4}})
A | B | C |
---|---|---|
1 |
2 |
null |
null |
3 |
4 |
The native type of table values is a custom table type (derived from the intrinsic type table
) that lists the column names, specifies all column types to be any, and has no keys. (Go to Table types for details on table types.)
Function
A function value is a value that maps a set of arguments to a single value. The details of function values are described in Functions.
Type
A type value is a value that classifies other values. The details of type values are described in Types.