值是透過計算表達式所產生的資料。 本節描述 M 語言中值的種類。 每種值類型都對應一個字面語法、一組屬於該類型的值、一組在該值集合上定義的運算子,以及賦予新建值的內在型態。
| 種類 | 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 ] |
以下章節將詳細介紹每種價值類型。 型別與型別歸屬在 「型別」中正式定義。 函數值定義於 函數中。 以下章節列出每種值類型定義的運算子並舉例說明。 運算子語意的完整定義詳見 《運算子》一文。
Null
空值用來表示值的缺失,或是狀態不確定或未知的值。 空值則使用文字 null。 以下運算子定義為零值:
| Operator | Result |
|---|---|
x > y |
大於 |
x >= y |
大於或等 |
x < y |
小於 |
x <= y |
小於或等於 |
x = y |
Equal |
x <> y |
不相等 |
x ?? y |
Coalesce |
該值的 null 本體型態為內在型態 null。
Logical
對於布林運算,邏輯 值 為真或假。 一個邏輯值是利用文字 true 和 false來寫的。 以下運算子定義為邏輯值:
| Operator | Result |
|---|---|
x > y |
大於 |
x >= y |
大於或等 |
x < y |
小於 |
x <= y |
小於或等於 |
x = y |
Equal |
x <> y |
不相等 |
x or y |
條件邏輯或 |
x ?? y |
Coalesce |
x and y |
條件邏輯 AND |
not x |
邏輯上不是 |
邏輯值(true 與 false)的原生型態即為內在型態 logical。
Number
數 值用於數 值與算術運算。 以下是數值的範例:
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)
數字的表示精度至少與 Double 相當(但可能保留更高精度)。 雙重表示法與 IEEE 64 位元雙精度二元浮點運算標準一致,該標準見於 [IEEE 754-2008]。 ( 雙重 表示法的動態範圍約為 5.0 x 10324 至 1.7 x 10308 ,精度為 15-16 位數。)
以下特殊值也被視為 數字 值:
正零和負零。 在大多數情況下,正零與負零的行為與簡單值零相同,但 某些運算會區分兩者。
正無限大(
#infinity)與負無限大(-#infinity)。 無窮大是通過將非零數除以零等運算產生的。 例如,會1.0 / 0.0得到正無限大,而-1.0 / 0.0則會產生負無限大。非數字值(
#nan),常縮寫為 NaN。 NaN 是由無效的浮點運算所產生,例如將零除以零。
二元數學運算使用 Precision。 精度決定運算元四捨五入的定義域及操作執行的定義域。 在沒有明確指定的精度的情況下,這類運算會使用 雙倍精度來執行。
如果數學運算的結果對目標格式來說太小,該運算的結果將變成正零或負零。
若數學運算結果對目標格式來說過大,該運算結果將變成正無限大或負無限大。
若數學運算無效,該運算結果即為 NaN。
如果浮點運算的一或兩個運算元是 NaN,則運算的結果會變成 NaN。
以下運算子定義於數值:
| Operator | Result |
|---|---|
x > y |
大於 |
x >= y |
大於或等 |
x < y |
小於 |
x <= y |
小於或等於 |
x = y |
Equal |
x <> y |
不相等 |
x + y |
Sum |
x - y |
Difference |
x * y |
Product |
x / y |
Quotient |
x ?? y |
Coalesce |
+x |
一元正號 |
-x |
Negation |
數字值的原生類型為內在類型 number。
Time
時間值儲存一個不透明的一天中時間表示。 時間以 午夜以來的滴答數編碼,計算24小時制中經過的100奈秒滴答數。 自午夜以來最大滴答數對應於23:59:59.9999999小時。
雖然沒有時間的字面語法,但提供了數個標準函式庫函式來構造時間。 時間也可以用內在函數 #time構造:
#time(hour, minute, second)
以下條件必須成立,否則會產生帶有原因代碼 Expression.Error 的錯誤:
0 ≤ ≤ 24
0 ≤ ≤ 59
0 ≤秒 ≤ 59
此外,若時=24,則分秒必須為零。
以下運算子定義時間值:
| Operator | Result |
|---|---|
x = y |
Equal |
x <> y |
不相等 |
x >= y |
大於或等 |
x > y |
大於 |
x < y |
小於 |
x <= y |
小於或等於 |
x ?? y |
Coalesce |
以下運算子允許其一個或兩個運算元為日期:
| Operator | 左操作數 | 右運算數 | Meaning |
|---|---|---|---|
x + y |
time |
duration |
日期依持續時間相抵 |
x + y |
duration |
time |
日期依持續時間相抵 |
x - y |
time |
duration |
日期抵消時長 |
x - y |
time |
time |
日期間隔 |
x & y |
date |
time |
合併日期時間 |
時間值的原生類型為內在型態 time。
Date
日期值儲存特定日期的不透明表示。 日期以自紀元起的 天數編碼,從公元公元1月1日開始。 自紀元以來的最大天數為3652058,對應於9999年12月31日。
雖然沒有日期的字面語法,但提供了幾個標準函式庫函式來構造日期。 日期也可以利用內在函數 #date構造:
#date(year, month, day)
以下條件必須成立,否則會產生帶有原因代碼 Expression.Error 的錯誤:
1 ≤年 ≤ 9999年
1 ≤月 ≤ 12
1 ≤ 31≤
此外,該日期必須對所選月份和年份有效。
以下運算子定義日期值:
| Operator | Result |
|---|---|
x = y |
Equal |
x <> y |
不相等 |
x >= y |
大於或等 |
x > y |
大於 |
x < y |
小於 |
x <= y |
小於或等於 |
x ?? y |
Coalesce |
以下運算子允許其一個或兩個運算元為日期:
| Operator | 左操作數 | 右運算數 | Meaning |
|---|---|---|---|
x + y |
date |
duration |
日期依持續時間相抵 |
x + y |
duration |
date |
日期依持續時間相抵 |
x - y |
date |
duration |
日期抵消時長 |
x - y |
date |
date |
日期間隔 |
x & y |
date |
time |
合併日期時間 |
日期值的原生類型為內在型態 date。
DateTime
datetime 值同時包含日期與時間。
雖然沒有字面上的日期時值語法,但提供了幾個標準函式庫函式來構建它們。 日期時間也可以用內在函數 #datetime構造:
#datetime(year, month, day, hour, minute, second)
以下必須保持或錯誤,且原因代碼為 Expression。錯誤被提出:1 ≤ 年 ≤ 9999
1 ≤月 ≤ 12
1 ≤ 31≤
0 ≤ ≤ 23
0 ≤ ≤ 59
0 ≤秒 ≤ 59
此外,該日期必須對所選月份和年份有效。
以下運算子定義為日期時間值:
| Operator | Result |
|---|---|
x = y |
Equal |
x <> y |
不相等 |
x >= y |
大於或等 |
x > y |
大於 |
x < y |
小於 |
x <= y |
小於或等於 |
x ?? y |
Coalesce |
以下運算子允許其一個或兩個運算元成為日期時間:
| Operator | 左操作數 | 右運算數 | Meaning |
|---|---|---|---|
x + y |
datetime |
duration |
日期時間依持續時間偏移 |
x + y |
duration |
datetime |
日期時間依持續時間偏移 |
x - y |
datetime |
duration |
Datetime 以消除時長抵消 |
x - y |
datetime |
datetime |
日期間隔 |
datetime 值的原生類型為內在型態 datetime。
DateTimeZone
DateTimezone 值包含一個 datetime 和一個時區。 時 區 以 與UTC偏移的分鐘數編碼,該時間 部分應與 世界協調時間(UTC)相差多少分鐘。 UTC的最小分鐘數偏移為-840分鐘,代表UTC偏移為-14:00,比UTC早十四小時。 UTC最大偏移分鐘數為840分鐘,對應14:00的UTC偏移。
雖然沒有明確的日期時區語法,但提供了幾個標準函式庫函式來構造它們。 日期時區也可以使用內在函數 #datetimezone構造:
#datetimezone(
year, month, day,
hour, minute, second,
offset-hours, offset-minutes)
以下條件必須成立,否則會產生帶有原因代碼 Expression.Error 的錯誤:
1 ≤年 ≤ 9999年
1 ≤月 ≤ 12
1 ≤ 31≤
0 ≤ ≤ 23
0 ≤ ≤ 59
0 ≤秒 ≤ 59
-14小時≤≤14小時
-59分鐘≤偏移分鐘≤59分鐘
此外,該日期必須對所選月份和年份有效,若偏移時數 = 14,則偏移分鐘 <= 0;若偏移時數 = -14,則偏移分鐘 >= 0。
以下運算子定義了日期時區的值:
| Operator | Result |
|---|---|
x = y |
Equal |
x <> y |
不相等 |
x >= y |
大於或等 |
x > y |
大於 |
x < y |
小於 |
x <= y |
小於或等於 |
x ?? y |
Coalesce |
以下營運商允許其一個或兩個操作元為日期時區:
| Operator | 左操作數 | 右運算數 | Meaning |
|---|---|---|---|
x + y |
datetimezone |
duration |
Datetimezone 依持續時間偏移 |
x + y |
duration |
datetimezone |
Datetimezone 依持續時間偏移 |
x - y |
datetimezone |
duration |
Datetimezone以消去的時長抵消 |
x - y |
datetimezone |
datetimezone |
日期時區間的持續時間 |
Datetimezone 值的原生類型為內在型態 datetimezone。
Duration
持續時間值儲存一個不透明的表示,表示時間軸上兩點之間的距離,測量為100奈秒刻。 持續時間的大小可以是正的或負的,正值表示時間向前的進展,負值則表示時間向後的進展。 在一個 持續時間 內可儲存的最小值為 -9,223,372,036,854,775,808 tick,或倒推 10,675,199 天 2 小時 48 分 05.4775808 秒。 每次 持續 時間內最大可儲存的值為 9,223,372,036,854,775,807 tick,或是 10,675,199 天 2 小時 48 分 05.4775807 秒。
雖然沒有字面上的語法來描述時值,但提供了幾個標準函式庫函式來構造時值。 持續時間也可用內徵函 #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
以下運算子定義於持續時間值上:
| Operator | Result |
|---|---|
x = y |
Equal |
x <> y |
不相等 |
x >= y |
大於或等 |
x > y |
大於 |
x < y |
小於 |
x <= y |
小於或等於 |
x ?? y |
Coalesce |
此外,以下運算子允許其中一個或兩個運算元為持續時間值:
| Operator | 左操作數 | 右運算數 | Meaning |
|---|---|---|---|
x + y |
datetime |
duration |
日期時間依持續時間偏移 |
x + y |
duration |
datetime |
日期時間依持續時間偏移 |
x + y |
duration |
duration |
持續時間總和 |
x - y |
datetime |
duration |
Datetime 以消除時長抵消 |
x - y |
datetime |
datetime |
日期間隔 |
x - y |
duration |
duration |
持續時間的差異 |
x * y |
duration |
number |
n 乘以持續時間 |
x * y |
number |
duration |
n 乘以持續時間 |
x / y |
duration |
number |
持續時間的分數 |
x / y |
duration |
duration |
持續時間的數值商 |
本來的持續時間類型為內在類型 duration。
文字
文字值代表一串 Unicode 字元。 文字值的字面形式符合以下文法:
_text-literal:
" 文字字元選擇"
文字字元:
文字字元-字元-文字-字元-字元 opt
text-literal-character:
single-text-character
character-escape-sequence
double-quote-escape-sequence
單文字字元:
除了 " (U+0022)或 # (U+0023)外,任何字元後面跟 ( 著(U+0028)
double-quote-escape-sequence:
"" (U+0022, U+0022)
以下是一個 文字 值的範例:
"ABC" // the text value ABC
以下運算子定義於 文字 值上:
| Operator | Result |
|---|---|
x = y |
Equal |
x <> y |
不相等 |
x >= y |
大於或等 |
x > y |
大於 |
x < y |
小於 |
x <= y |
小於或等於 |
x & y |
Concatenation |
x ?? y |
Coalesce |
文本值的原生類型為內在類型 text。
Binary
二進位值代表一串位元組。
雖然二進位值沒有字面上的語法,但提供了幾個標準函式庫函式來構造它們。 二元值也可用內徵函 #binary數 來構造。
以下範例從一個位元組清單中構造出二進位值:
#binary( {0x00, 0x01, 0x02, 0x03} )
以下運算子定義於 二進位 值:
| Operator | Result |
|---|---|
x = y |
Equal |
x <> y |
不相等 |
x >= y |
大於或等 |
x > y |
大於 |
x < y |
小於 |
x <= y |
小於或等於 |
x ?? y |
Coalesce |
二進位值的原生型態是內在型 二元值。
List
列表值是指在列舉時產生一連串值的值。 由串列產生的值可以包含任何類型的值,包括一個串列。 列表可使用初始化語法構建,具體如下:
list-expression:
{ 項目清單選擇 }
項目清單:
項目
項目,項目清單
item:
運算式
表達..式
以下是一個列表 表達 式的範例,定義了一個包含三個文字值的列表: "A"、、 "B"和 "C"。
{"A", "B", "C"}
值 "A" 是清單中的第一個項目,值 "C" 是列表中的最後一個項目。
- 清單中的項目在被存取之前不會被評估。
- 雖然使用清單語法建構的清單值會依照項目 列表中出現的順序產生項目,但一般而言,從函式庫函式回傳的列表每次列舉時可能會產生不同的集合或不同數量的值。
若要在列表中包含整數序列,可以使用以下 a..b 形式:
{ 1, 5..9, 11 } // { 1, 5, 6, 7, 8, 9, 11 }
清單中的項目數量,稱為 清單數量,可以透過該 List.Count 函數來確定。
List.Count({true, false}) // 2
List.Count({}) // 0
一個清單實際上可以包含無限數量的項目; List.Count 因為此類列表未定義,可能產生錯誤或不終止。
如果清單中沒有任何項目,則稱為 空清單。 空清單寫成:
{} // empty list
以下運算子被定義用於列表:
| Operator | Result |
|---|---|
x = y |
Equal |
x <> y |
不相等 |
x & y |
Concatenate |
x ?? y |
Coalesce |
例如:
{1, 2} & {3, 4, 5} // {1, 2, 3, 4, 5}
{1, 2} = {1, 2} // true
{2, 1} <> {1, 2} // true
列表值的原生類型是內在型態 list,它指定了 的項目類型。any
Record
記錄值是一串有序的欄位序列。 欄位由欄位名稱(欄位名稱)組成,該欄位是唯一識別記錄中欄位的文字值,以及欄位值。 欄位值可以是任何類型的值,包括記錄值。 記錄可用初始化語法建構,具體如下:
record-expression:
[
場地列表OPT]
田野名單:
欄位
田野,名錄
field:
欄位名稱=表達式
field-name:
generalized-identifier
引用識別碼
以下範例構造一個記錄,其欄位為 x1,值為 ,以及一個名為 y2的欄位。
[ x = 1, y = 2 ]
以下範例構造一個名為 a a 的欄位,且帶有巢狀記錄值。 巢狀記錄有一個名為 b 的欄位,值為 2。
[ a = [ b = 2 ] ]
評估記錄表達式時,以下情況成立:
每個欄位名稱所指派的表達式用來決定該欄位的值。
如果賦值欄位名稱的表達式在評估時產生一個值,那麼該值就成為結果記錄欄位的值。
若欄位名稱的表達式在評估時產生錯誤,則錯誤的事實會與欄位一同記錄,連同錯誤值一併記錄。 後續存取該欄位時,錯誤會以記錄值重新提出。
在像父環境這樣的環境中,只有合併變數時才會評估,這些變數對應記錄中除初始化欄位外的所有欄位的值。
記錄中的值在存取對應欄位後才會被評估。
記錄中的一個值最多會被評估一次。
該表達式的結果是一個帶有空元資料記錄的記錄值。
記錄中欄位的順序由它們在 記錄初始化運算式中出現的順序決定。
每個欄位名稱必須在紀錄中唯一,否則就是錯誤。 名稱是透過序數比較來比較的。
[ x = 1, x = 2 ] // error: field names must be unique
[ X = 1, x = 2 ] // OK
沒有欄位的紀錄稱為 空記錄,寫作方式如下:
[] // empty record
雖然在存取欄位或比較兩筆記錄時,欄位的順序並不重要,但在其他情境中則很重要,例如當記錄欄位被列舉時。
當取得欄位時,這兩個紀錄會產生不同的結果:
Record.FieldNames([ x = 1, y = 2 ]) // [ "x", "y" ]
Record.FieldNames([ y = 1, x = 2 ]) // [ "y", "x" ]
記錄中的欄位數量可以用函 Record.FieldCount 數來確定。 例如:
Record.FieldCount([ x = 1, y = 2 ]) // 2
Record.FieldCount([]) // 0
除了使用記錄初始化語法 [ ]外,紀錄還可以由值清單、欄位名稱清單或紀錄類型來構造。 例如:
Record.FromList({1, 2}, {"a", "b"})
上述等價於:
[ a = 1, b = 2 ]
以下運算子定義為記錄值:
| Operator | Result |
|---|---|
x = y |
Equal |
x <> y |
不相等 |
x & y |
Merge |
x ?? y |
Coalesce |
以下範例說明上述運算子。 請注意,記錄合併會使用右側運算元欄位來覆蓋左側運算元欄位,以防欄位名稱有重疊。
[ 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
記錄值的原生類型是內在型態 record,它指定了一個開放的空欄位清單。
Table
表值是一列有序的列。 列是一串有序的欄位值序列。 資料表的類型決定了所有資料列的長度、資料表欄位名稱、欄位的類型,以及資料表鍵的結構(如果有的話)。
雖然沒有字面上的表格語法,但提供了數個標準函式庫函式來構建它們。 表格也可以利用內在函數 #table來構造。
以下範例從欄位名稱清單和列清單中構建一個表格。 結果的表格將包含兩欄 type any 和三列。
#table({"x", "x^2"}, {{1,1}, {2,4}, {3,9}})
#table 也可以用來指定完整的資料表類型:
#table(
type table [Digit = number, Name = text],
{{1,"one"}, {2,"two"}, {3,"three"}}
)
此處新資料表值有一個表型別,指定欄位名稱與欄位類型。
以下運算子定義為表格值:
| Operator | Result |
|---|---|
x = y |
Equal |
x <> y |
不相等 |
x & y |
Concatenation |
x ?? y |
Coalesce |
資料表串接會對齊同名欄位,並填 null 補只出現在其中一個運算元表中的欄位。 以下範例說明表格串接:
#table({"A","B"}, {{1,2}})
& #table({"B","C"}, {{3,4}})
| A | B | C |
|---|---|---|
1 |
2 |
null |
null |
3 |
4 |
表值的原生型態是一種自訂型態(源自內在型別 table),列出欄位名稱,指定所有欄位類型為任意,且沒有鍵值。 (詳情請參閱 表格類型 。)
Function
函數值是將一組參數映射到單一值的值。 函數值的細節詳見函數部分。
類型
型別值是用來分類其他值的值。 類型值的細節詳見「類型」一節。