本節定義各種 M 運算子的行為。
運算子優先順序
當運算式包含多個運算子時,運算子的「優先順序」會控制評估個別運算子的順序。 例如,運算式 x + y * z 會評估為 x + (y * z),因為 * 運算子的優先順序高於二元 + 運算子。 運算子優先順序是由其相關聯文法結果的定義所建立。 例如,「加法類運算式」是由 或 + 運算子分隔的「乘法類運算式」-序列所組成,因此 + 和 - 運算子的優先順序會低於 * 和 / 運算子。
「加括弧的運算式」結果可用來變更預設優先順序。
parenthesized-expression:
(
運算式)
例如:
1 + 2 * 3 // 7
(1 + 2) * 3 // 9
下表摘要說明 M 運算子,並依序 (從最高優先順序到最低優先順序) 列出運算子類別。 相同分類中的運算子具有相等的優先順序。
| 類別 | 運算式 | 描述 |
|---|---|---|
| Primary |
i @ 我 |
識別碼運算式 |
| (x) | 加括弧的運算式 | |
| x[i] | 查閱 | |
| x{y} | 項目存取 | |
| x(...) | 函式引動過程 | |
| {x, y, ...} | 清單初始化 | |
| [ i = x, ... ] | 記錄初始化 | |
| ... | 未實作 | |
| 一元 | + x | 身分識別 |
| - x | 否定 | |
not
x |
邏輯否定 | |
| 中繼資料 |
xmetay |
關聯中繼資料 |
| 乘法 | x * y | 乘法 |
| x / y | 部門 | |
| 加法 | x + y | 加法 |
| x - y | 減 | |
| 關聯式 | x< y | 小於 |
| x > y | 大於 | |
| x<= y | 小於或等於 | |
| x >= y | 大於或等於 | |
| Equality | x = y | 等於 |
| x<> y | 不等於 | |
| 類型判斷提示 |
xasy |
相容的原始/可空的原始類型或錯誤 |
| 類型一致性 |
xisy |
測試型別是否與原始型別或可消除原始型別相容 |
| 邏輯 AND |
xandy |
最少運算結合 |
| 邏輯 OR |
xory |
最少運算分離 |
| Coalesce |
x??y |
Null 聯合運算子 |
運算子和中繼資料
每個值都有相關聯的記錄值,可包含該值的其他資訊。 此記錄稱為值的「中繼資料記錄」。 中繼資料記錄可以與任何類型的值建立關聯,甚至是 null。 這類關聯結果就是具有指定中繼資料的新值。
中繼資料記錄只是一般記錄,可以包含一般記錄所能包含的任何欄位和值,且本身就有中繼資料記錄。 建立中繼資料記錄與值的關聯「不會造成干擾」。 不會在評估時變更值的行為,但明確檢查中繼資料記錄的評估則除外。
每個值都有預設中繼資料記錄,即使尚未指定一個也一樣。 預設中繼資料記錄為空白。 下列範例說明如何使用 Value.Metadata 標準程式庫函式來存取文字值的中繼資料記錄:
Value.Metadata( "Mozart" ) // []
若搭配建構新值的運算子或函式使用值,通常「不會保留」中繼資料記錄。 例如,若使用 & 運算子將兩個文字值串連,則所產生文字值的中繼資料會是空白記錄 []。 下列運算式是對等的:
"Amadeus " & ("Mozart" meta [ Rating = 5 ])
"Amadeus " & "Mozart"
標準程式庫函式 Value.RemoveMetadata 和 Value.ReplaceMetadata 可以用來移除值的所有中繼資料,以及取代值的中繼資料 (而不是將中繼資料合併到可能存在的中繼資料)。
唯一會傳回包含中繼資料結果的運算子是 meta 運算子。
結構遞迴運算子
值可以「循環」。 例如:
let l = {0, @l} in l
// {0, {0, {0, ... }}}
[A={B}, B={A}]
// [A = {{ ... }}, B = {{ ... }}]
M 會藉由保持記錄、清單和資料表延遲的建構來處理循環值。 嘗試建構不會受益於插入延遲結構化值的循環值會產生錯誤:
[A=B, B=A]
// [A = Error.Record("Expression.Error",
// "A cyclic reference was encountered during evaluation"),
// B = Error.Record("Expression.Error",
// "A cyclic reference was encountered during evaluation"),
// ]
M 中的某些運算子是由結構遞迴所定義。 例如,記錄和清單的等式,分別是由對應記錄欄位和項目清單的結合等式所定義。
針對非循環值,套用結構遞迴會產生值的「有限展開」:共用的巢狀值會重複地周遊,但遞迴處理一律會終止。
套用結構遞迴時,循環值會有「無限展開」。 M 的語意不會特別挪出空間給這類無限展開 - 嘗試比較循環值是否相等,通常會耗盡資源而異常終止。
選取和投影運算子
選取和投影運算子可供從清單和記錄值中擷取資料。
項目存取
您可使用 item-access-expression,以根據清單或資料表中以零為基底的位置,從清單或資料表中選取值。
項目存取表達式:
item-selection
optional-item-selection
item-selection:
主要表達{式項目選擇器}
可選項目選擇:
主要表達{式項目選擇器} ?
物品選擇器:
詞
item-access-expressionx{y} 會傳回:
對於清單
x和數字y,這會傳回清單x中位置為y的項目。 清單中第一個項目會視為具有零的序數索引。 如果要求的位置不存在於清單中,則會引發錯誤。對於資料表
x和數字y,這會傳回資料表x中位置為y的資料列。 資料表中第一個資料列會視為具有零的序數索引。 如果要求的位置不存在於資料表中,則會引發錯誤。對於資料表
x和記錄y,這會傳回資料表x中符合欄位記錄y的欄位值資料列 (其欄位名稱符合對應的資料表資料行名稱)。 如果資料表中沒有唯一相符的資料列,則會引發錯誤。
例如:
{"a","b","c"}{0} // "a"
{1, [A=2], 3}{1} // [A=2]
{true, false}{2} // error
#table({"A","B"},{{0,1},{2,1}}){0} // [A=0,B=1]
#table({"A","B"},{{0,1},{2,1}}){[A=2]} // [A=2,B=1]
#table({"A","B"},{{0,1},{2,1}}){[B=3]} // error
#table({"A","B"},{{0,1},{2,1}}){[B=1]} // error
item-access-expression 也支援 x{y}? 格式,這會在位置 (或相符項目) null 不存在於清單或資料表 y 中時傳回 x。 如果 y 有多個相符項目,仍會引發錯誤。
例如:
{"a","b","c"}{0}? // "a"
{1, [A=2], 3}{1}? // [A=2]
{true, false}{2}? // null
#table({"A","B"},{{0,1},{2,1}}){0}? // [A=0,B=1]
#table({"A","B"},{{0,1},{2,1}}){[A=2]}? // [A=2,B=1]
#table({"A","B"},{{0,1},{2,1}}){[B=3]}? // null
#table({"A","B"},{{0,1},{2,1}}){[B=1]}? // error
項目存取除了所存取的清單或資料表項目之外,不會強制評估其他項目。 例如:
{ error "a", 1, error "c"}{1} // 1
{ error "a", error "b"}{1} // error "b"
評估項目存取運算子 x{y} 時會發生下列情況:
評估運算式
x或y期間所引發的錯誤會進行傳播。運算式
x會產生清單或資料表值。運算式
y會產生數值;如果x產生資料表值,則會產生記錄值。如果
y產生數值,且y的值為負數,則會引發原因代碼為"Expression.Error"的錯誤。如果
y產生數值,且y的值大於或等於x的計數,則會引發原因代碼為"Expression.Error"的錯誤,除非使用選用運算子格式x{y}?,在此情況下會傳回null值。如果
x產生資料表值,而y產生記錄值,且y中沒有x的任何相符項目,則會引發原因代碼為"Expression.Error"的錯誤,除非使用選用運算子格式x{y}?,在此情況下會傳回null值。如果
x產生資料表值,而y產生記錄值,且y中沒有x的多個相符項目,則會引發原因代碼為"Expression.Error"的錯誤。
在項目選取的過程中,只會評估 x 中位置為 y 的項目 (針對串流清單或資料表,位置 y 前面的項目或資料列會被略過,視清單或資料表的來源而定,這可能會造成對其進行評估)。
欄位存取
field-access-expression 可用來從記錄中「選取」值,或將記錄或資料表分別「投影」到具有較少欄位或資料行的記錄或資料表。
field-access-expression:
field-selection
implicit-target-field-selection
投影
implicit-target-projection
field-selection:
主表達式欄位選擇器
field-selector:
required-field-selector
optional-field-selector
必要欄位選擇器:
[
田名]
optional-field-selector:
[
田名] ?
田名:
generalized-identifier
quoted-identifier
implicit-target-field-selection:
field-selector
projection:
主要表達式需求投影
主表達式可選投影
必要投影:
[
必要選擇器列表]
optional-projection:
[
必要選擇器列表] ?
必要選擇器清單:
required-field-selector
必要選擇器列表,必要欄位選擇器
implicit-target-projection:
required-projection
可選投影
欄位存取的最簡單格式是「必要欄位選取」。 其使用運算子 x[y] 來依欄位名稱查閱記錄中的欄位。 如果欄位 y 不存在於 x 中,則會引發錯誤。
x[y]? 格式可用來執行「選用」欄位選取;如果要求的欄位不存在於記錄中,則會傳回 null。
例如:
[A=1,B=2][B] // 2
[A=1,B=2][C] // error
[A=1,B=2][C]? // null
「必要記錄投影」和「選用記錄投影」的運算子支援集體存取多個欄位。 運算子 x[[y1],[y2],...] 會將記錄投影到具有較少欄位 (由 y1, y2, ... 所選取) 的新記錄。 如果選取的欄位不存在,則會引發錯誤。 運算子 x[[y1],[y2],...]? 會將記錄投影到具有由 y1, y2, ... 所選取欄位的新記錄;如果遺漏欄位,則會改用 null。
例如:
[A=1,B=2][[B]] // [B=2]
[A=1,B=2][[C]] // error
[A=1,B=2][[B],[C]]? // [B=2,C=null]
支援使用 [y] 和 [y]? 格式作為識別項 (底線) 的「速記」_參考。 下列兩個運算式是對等的:
[A]
_[A]
下列範例說明欄位存取的速記格式:
let _ = [A=1,B=2] in [A] //1
此外,也支援使用 [[y1],[y2],...] 和 [[y1],[y2],...]? 作為速記,而下列兩個運算式同樣是對等的:
[[A],[B]]
_[[A],[B]]
速記格式結合 each 速記時會特別有用,這可供引進名為 _ 單一參數的函式 (如需詳細資訊,請參閱簡化的宣告)。 這兩個速記搭配使用可簡化一般較高階的函式運算式:
List.Select( {[a=1, b=1], [a=2, b=4]}, each [a] = [b])
// {[a=1, b=1]}
上述運算式相當於下列更難懂的普通寫法:
List.Select( {[a=1, b=1], [a=2, b=4]}, (_) => _[a] = _[b])
// {[a=1, b=1]}
欄位存取除了所存取的欄位之外,不會強制評估其他欄位。 例如:
[A=error "a", B=1, C=error "c"][B] // 1
[A=error "a", B=error "b"][B] // error "b"
評估欄位存取運算子 x[y]、x[y]?、x[[y]] 或 x[[y]]? 時會發生下列情況:
評估運算式
x期間所引發的錯誤會進行傳播。評估欄位
y時所引發的錯誤會與欄位y永久建立關聯,然後進行傳播。 未來對欄位y的任何存取都將引發相同的錯誤。運算式
x會產生記錄或資料表值,或是引發錯誤。如果識別項
y所命名的欄位不存在於x中,則會引發原因代碼為"Expression.Error"的錯誤,除非使用選用運算子格式...?,在此情況下會傳回null值。
在欄位存取的過程中,只會評估 x 中 y 所命名的欄位。
中繼資料運算子
您可使用「meta 運算子」(x meta y) 來修改值的中繼資料記錄。
metadata-expression:
unary-expression
一元表達meta式一元表達式
下列範例會使用 meta 運算子來建構具有中繼資料記錄的文字值,然後使用 Value.Metadata 來存取所產生值的中繼資料記錄:
Value.Metadata( "Mozart" meta [ Rating = 5 ] )
// [Rating = 5 ]
Value.Metadata( "Mozart" meta [ Rating = 5 ] )[Rating]
// 5
套用結合運算子 x meta y 的中繼資料時會發生下列情況:
評估
x或y運算式時所引發的錯誤會進行傳播。y運算式必須是記錄,否則會引發原因代碼為"Expression.Error"的錯誤。所產生中繼資料記錄是與
x合併的y中繼資料記錄 (如需記錄合併的語意,請參閱記錄合併)。所產生值是來自
x運算式的值,不含其中繼資料,而是附加新計算的中繼資料記錄。
標準程式庫函式 Value.RemoveMetadata 和 Value.ReplaceMetadata 可以用來移除值的所有中繼資料,以及取代值的中繼資料 (而不是將中繼資料合併到可能存在的中繼資料)。 下列運算式是對等的:
x meta y
Value.ReplaceMetadata(x, Value.Metadata(x) & y)
Value.RemoveMetadata(x) meta (Value.Metadata(x) & y)
等號比較運算子
等號比較運算子= 用來判斷兩個值是否相等。
不等比較運算子<> 用來判斷兩個值是否不相等。
等式表達:
relational-expression
關係表達=式等式表達
關係表達<>式等式表達
例如:
1 = 1 // true
1 = 2 // false
1 <> 1 // false
1 <> 2 // true
null = true // false
null = null // true
中繼資料不屬於等號比較或不等比較的一部分。 例如:
(1 meta [ a = 1 ]) = (1 meta [ a = 2 ]) // true
(1 meta [ a = 1 ]) = 1 // true
套用等號比較運算子 x = y 和 x <> y 時會發生下列情況:
評估
x或y運算式時所引發的錯誤會進行傳播。如果值相等,則
=運算子的結果為true;否則為false。如果值相等,則
<>運算子的結果為false;否則為true。中繼資料記錄不會包含在比較中。
如果評估
x和y運算式所產生值不是相同類型的值,則值不相等。如果評估
x和y運算式所產生值是相同類型的值,則會透過特定規則來判斷是否相等,如下所定義。下列條件一律成立:
(x = y) = not (x <> y)
等號比較運算子是針對下列類型所定義:
-
null值只等於其本身。
null = null // true
null = true // false
null = false // false
- 邏輯值
true和false只等於其本身。 例如:
true = true // true
false = false // true
true = false // false
true = 1 // false
數字會使用指定的精確度來進行比較:
如果任一個數字為
#nan,則數字不同。如果任一個數字都不是
#nan,則數字會使用數值的位元比較來進行比較。#nan是唯一不等於其本身的值。例如:
1 = 1, // true
1.0 = 1 // true
2 = 1 // false
#nan = #nan // false
#nan <> #nan // true
如果兩個期間代表相同的 100 奈秒刻度數,則相等。
如果兩個時間部分 (小時、分鐘、秒) 的大小相等,則相等。
如果兩個日期部分 (年、月、日) 的大小相等,則相等。
如果兩個日期時間部分 (年、月、日、小時、分鐘、秒) 的大小相等,則相等。
如果兩個日期時區的對應 UTC 日期時間相等,則相等。 為了達到對應的 UTC 日期時間,會從日期時區的日期時間元件減去小時/分鐘位移。
如果使用序數、區分大小寫、不區分文化特性的比較,則兩個文字值相等,其長度相同且在對應位置有相等字元。
如果符合下列所有條件,則兩個清單值相等:
兩個清單所包含的項目數相同。
清單中每個對應位置的項目值都相等。 這表示清單不只需要包含相等的項目數,項目的順序也必須相同。
例如:
{1, 2} = {1, 2} // true {2, 1} = {1, 2} // false {1, 2, 3} = {1, 2} // false
如果符合下列所有條件,則兩個記錄相等:
欄位數目相同。
一個記錄的每個欄位名稱也會出現在另一個記錄中。
一個記錄的每個欄位值都等於另一個記錄中同名欄位。
例如:
[ A = 1, B = 2 ] = [ A = 1, B = 2 ] // true [ B = 2, A = 1 ] = [ A = 1, B = 2 ] // true [ A = 1, B = 2, C = 3 ] = [ A = 1, B = 2 ] // false [ A = 1 ] = [ A = 1, B = 2 ] // false
如果符合下列所有條件,則兩個資料表相等:
資料行數目相同。
一個資料表中的每個資料行名稱也會出現在另一個資料表中。
資料列數目相同。
每個資料列在對應的資料格中都有相等值。
例如:
#table({"A","B"},{{1,2}}) = #table({"A","B"},{{1,2}}) // true #table({"A","B"},{{1,2}}) = #table({"X","Y"},{{1,2}}) // false #table({"A","B"},{{1,2}}) = #table({"B","A"},{{2,1}}) // true
函式值等於其本身,但不一定等於另一個函式值。 如果兩個函式值視為相等,則在叫用時會有相同的行為。
兩個指定的函式值一律會有相同等號比較關係。
類型值等於其本身,但不一定等於另一個類型值。 如果兩個類型值視為相等,則在查詢一致性時會有相同的行為。
兩個指定的類型值一律會有相同等號比較關係。
關聯式運算子
<、>、<= 和 >= 運算子稱為「關係運算子」。
關係表達式:
additive-expression
加法表達<式關係表達式
加法表達>式關係表達式
加法表達<=式關係表達式
加法表達>=式關係表達式
這些運算子可用來判斷兩個值之間的相對順序關係,如下表所示:
| 作業 | 結果 |
|---|---|
x < y |
若 true 小於 x 則為 y;否則為 false |
x > y |
若 true 大於 x 則為 y;否則為 false |
x <= y |
若 true 小於或等於 x 則為 y;否則為 false |
x >= y |
若 true 大於或等於 x 則為 y;否則為 false |
例如:
0 <= 1 // true
null < 1 // null
null <= null // null
"ab" < "abc" // true
#nan >= #nan // false
#nan <= #nan // false
評估包含關係運算子的運算式時會發生下列情況:
評估
x或y運算元運算式時所引發的錯誤會進行傳播。評估
x和y運算式所產生的值必須是二進位、日期、日期時間、日期時區、期間、邏輯、數字、Null、文字或時間值。 否則,就會引發原因代碼為"Expression.Error"的錯誤。這兩個運算元都必須是相同種類的值或
null。 否則,就會引發原因代碼為"Expression.Error"的錯誤。如果其中一或兩個運算元為
null,則結果為null值。兩個二進位會逐個位元組進行比較。
兩個日期的比較方式是先比較其年部分;若相等,則比較其月部分;若相等,則比較其日部分。
兩個日期時間的比較方式是先比較其年部分;若相等,則比較其月部分;若相等,則比較其日部分;若相等,則比較其小時部分;若相等,則比較其分鐘部分;若相等,則比較其秒部分。
兩個日期時區的比較方式是先藉由減去其小時/分鐘位移來將其正規化為 UTC,再比較其日期時間元件。
兩個持續時間會根據其所代表的 100 奈秒刻度總數來進行比較。
兩個邏輯會進行比較,使得
true被視為大於false。兩個數字
x和y會根據 IEEE 754 標準的規則進行比較:如果任一個運算元為
#nan,則所有關係運算子的結果都為false。當運算元都不是
#nan時,運算子會根據排序-∞ < -max < ... < -min < -0.0 = +0.0 < +min < ... < +max < +∞比較兩個浮點運算元,其中 min 和 max 是可以表示的最小和最大正有限值。 -∞ 和 +∞ 的 M 名稱是-#infinity和#infinity。此順序值得注意的影響如下:
負零和正零會視為相等。
-#infinity值會視為小於其他所有數值,但等於另一個-#infinity。#infinity值會視為大於其他所有數值,但等於另一個#infinity。
兩個文字的比較方式是使用逐字元序數、區分大小寫、不區分文化特性的比較。
兩個時間的比較方式是先比較其小時部分;若相等,則比較其分鐘部分;若相等,則比較其秒部分。
條件邏輯運算子
and 和 or 運算子稱為條件邏輯運算子。
邏輯或表達式:
邏輯與表達
式 邏輯與表達or式 邏輯或表達式
logical-and-expression:
is-expression
is-表達and式邏輯與表達式
當至少有一個運算元為 or 時,true 運算子會傳回 true。 只有在左運算元不是 true 時,才會評估右運算元。
當至少有一個運算元為 and 時,false 運算子會傳回 false。 只有在左運算元不是 false 時,才會評估右運算元。
以下顯示 or 和 and 運算子的事實資料表,其中包含評估垂直軸上左運算元運算式的結果,以及評估水平軸上右運算元運算式的結果。
and |
true |
false |
null |
error |
|---|---|---|---|---|
true |
true |
false |
null |
error |
false |
false |
false |
false |
false |
null |
null |
false |
null |
error |
error |
error |
error |
error |
error |
or |
true |
false |
null |
error |
|---|---|---|---|---|
or |
true |
false |
null |
error |
true |
true |
true |
true |
true |
false |
true |
false |
null |
error |
null |
true |
null |
null |
error |
error |
error |
error |
error |
error |
評估包含條件邏輯運算子的運算式時會發生下列情況:
評估
x或y運算式時所引發的錯誤會進行傳播。條件邏輯運算子是透過
logical和null類型所定義。 如果運算元的值不是這些類型,則會引發原因代碼為"Expression.Error"的錯誤。結果會是邏輯值。
在運算式
x或y中,只有在y未評估為x時,才會評估運算式true。在運算式
x和y中,只有在y未評估為x時,才會評估運算式false。
最後兩個屬性會為條件邏輯運算子提供「條件」資格;這些屬性也稱為「最少運算」。 這些屬性很適合用來撰寫精簡的「成立條件述詞」。 例如,下列運算式是對等的:
d <> 0 and n/d > 1 if d <> 0 then n/d > 1 else false
算術運算子
+、-、* 和 / 運算子是「算術運算子」。
加法表達式:
multiplicative-expression
加法表達+式乘法表達式
加法表達-式乘法表達式
multiplicative-expression:
metadata-expression
乘法表達*式元資料表達式
乘法表達/式元資料表達式
精確度
M 中數字會使用各種不同的表示法來儲存,以盡可能保留來自各種來源數字的最多資訊。 這些數字只會在所套用的運算子需要時,才會從一個表示法轉換成另一個。 M 支援兩種精確度:
| 精確度 | 語意 |
|---|---|
Precision.Decimal |
128 位元十進位表示法,其範圍介於 ±1.0 x 10-28 到 ±7.9 x 1028 之間,有效位數為 28-29。 |
Precision.Double |
使用尾數和指數的科學表示法;符合 64 位元二進位雙精確度 IEEE 754 算術標準 IEEE 754-2008。 |
算數運算的執行方式是選擇精確度,並將兩個運算元轉換成該精確度 (如有需要),然後執行實際運算,最後再以選擇的精確度傳回數字。
內建算術運算子 (+、-、*、/) 使用雙精確度。 標準程式庫函式 (Value.Add、Value.Subtract、Value.Multiply、Value.Divide) 可用來要求這些運算使用特定精確度模型。
不可能發生數值溢位:
#infinity或-#infinity代表太大而無法表示的大小值。不可能發生數值反向溢位:
0和-0代表太小而無法表示的大小值。IEEE 754 特殊值
#nan(NaN - 不是數字) 可用來涵蓋算術無效的案例,例如零除以零。若要將十進位精確度轉換成雙精確度,請將十進位數字四捨五入到最近的對等雙精確度值。
若要將雙精確度轉換成十進位精確度,請將雙精確度數字四捨五入到最近的對等十進位值,並視需要滿溢到
#infinity或-#infinity值。
加法運算子
加法運算子 (x + y) 的解讀會相依於所評估運算式 x 和 y 的值類型,如下所示:
| x | y | 結果 | 解釋 |
|---|---|---|---|
type number |
type number |
type number |
數值總和 |
type number |
null |
null |
|
null |
type number |
null |
|
type duration |
type duration |
type duration |
大小的數值總和 |
type duration |
null |
null |
|
null |
type duration |
null |
|
type
日期時間 |
type duration |
type
日期時間 |
依據期間位移後的日期時間 |
type duration |
type
日期時間 |
type
日期時間 |
|
type
日期時間 |
null |
null |
|
null |
type
日期時間 |
null |
在上表中,type日期時間代表 type date、type datetime、type datetimezone 或 type time 的任何一種。 當某個「日期時間」類型的期間和值相加時,所產生值會是相同的類型。
若不是表格中所列的值組合,則會引發原因代碼為 "Expression.Error" 的錯誤。 下列各節將說明每個組合。
評估任一運算式元時所引發的錯誤會進行傳播。
數值總和
兩個數字的總和是使用「加法運算子」進行計算,以產生一個數字。
例如:
1 + 1 // 2
#nan + #infinity // #nan
數字上的加法運算子 + 使用雙精確度;標準程式庫函式 Value.Add 可用來指定十進位精確度。 計算數字總和時會發生下列情況:
雙精確度中總和會根據 64 位元二進位雙精確度 IEEE 754 算術 IEEE 754-2008 的規則進行計算。 下表列出非零有限值、零、無限大和 NaN 所有可能組合的結果。 在下表中,
x和y是非零有限值,而z是x + y的結果。 如果x和y具有相同的大小,但正負號相反,則z為正零。 如果x + y太大,而無法以目的地類型表示,則z會是具有與x + y相同正負號的無限大。+ y +0 0- +∞ -∞ NAN x z x x +∞ -∞ NAN +0 y +0 +0 +∞ -∞ NAN -0 y +0 0- +∞ -∞ NAN +∞ +∞ +∞ +∞ +∞ NAN NAN -∞ -∞ -∞ -∞ NAN -∞ NAN NaN NAN NAN NAN NAN NAN NAN 計算十進位精確度的總和,而不會失去精確度。 結果其小數位數大於兩個運算元的小數位數。
期間的總和
兩個期間其總和是以期間所代表 100 奈秒刻度數總和所表示的期間。 例如:
#duration(2,1,0,15.1) + #duration(0,1,30,45.3)
// #duration(2, 2, 31, 0.4)
依據期間位移後的日期時間
日期時間x 和期間 y 可能會使用 x + y 相加,以計算新的日期時間,其與線性時間軸上的 x 距離會完全等於 y 的大小。 在這裡,「日期時間」代表任何 Date、DateTime、DateTimeZone 或 Time,而非 Null 的結果會是相同類型。 依據期間位移後的日期時間計算方式可能如下:
如果指定日期時間從 Epoch 至今的天數值,請使用下列資訊項目來建構新的日期時間:
計算 Epoch 至今的新天數,相當於將 y 的大小除以 24 小時內 100 奈秒刻度數、截斷結果的小數部分,然後將此值加上 x 從 Epoch 至今的天數。
計算從午夜起算的新刻度數,相當於將 y 的大小加上 x 從午夜起算的刻度數,然後對 24 小時內的 100 奈秒刻度數進行模數運算。 如果 x 未指定從午夜起算的刻度數,則假設值為 0。
複製 x 的值,因為 UTC 的分鐘位移不變。
如果未指定日期時間從 Epoch 值至今的天數,請使用下列指定的資訊項目來建構新的日期時間:
計算從午夜起算的新刻度數,相當於將 y 的大小加上 x 從午夜起算的刻度數,然後對 24 小時內的 100 奈秒刻度數進行模數運算。 如果 x 未指定從午夜起算的刻度數,則假設值為 0。
複製 x 從 Epoch 至今的天數值,以及 UTC 的分鐘位移。
下列範例說明當日期時間指定「從 Epoch 至今的天數」時,如何計算絕對時態性總和:
#date(2010,05,20) + #duration(0,8,0,0)
//#datetime( 2010, 5, 20, 8, 0, 0 )
//2010-05-20T08:00:00
#date(2010,01,31) + #duration(30,08,0,0)
//#datetime(2010, 3, 2, 8, 0, 0)
//2010-03-02T08:00:00
#datetime(2010,05,20,12,00,00,-08) + #duration(0,04,30,00)
//#datetime(2010, 5, 20, 16, 30, 0, -8, 0)
//2010-05-20T16:30:00-08:00
#datetime(2010,10,10,0,0,0,0) + #duration(1,0,0,0)
//#datetime(2010, 10, 11, 0, 0, 0, 0, 0)
//2010-10-11T00:00:00+00:00
下列範例說明如何計算指定時間其依據期間位移後的日期時間:
#time(8,0,0) + #duration(30,5,0,0)
//#time(13, 0, 0)
//13:00:00
減法運算子
減法運算子 (x - y) 其解讀會相依於所評估運算式 x 和 y 的值類型,如下所示:
| x | Y | 結果 | 解釋 |
|---|---|---|---|
type number |
type number |
type number |
數值差 |
type number |
null |
null |
|
null |
type number |
null |
|
type duration |
type duration |
type duration |
大小的數值差 |
type duration |
null |
null |
|
null |
type duration |
null |
|
type
日期時間 |
type
日期時間 |
type duration |
日期時間之間的期間 |
type
日期時間 |
type duration |
type
日期時間 |
依據負期間位移後的日期時間 |
type
日期時間 |
null |
null |
|
null |
type
日期時間 |
null |
在上表中,type日期時間代表 type date、type datetime、type datetimezone 或 type time 的任何一種。 從某個「日期時間」類型的值中減去期間時,所產生值會是相同的類型。
若不是表格中所列的值組合,則會引發原因代碼為 "Expression.Error" 的錯誤。 下列各節將說明每個組合。
評估任一運算式元時所引發的錯誤會進行傳播。
數值差
兩個數字之間的差是使用「減法運算子」進行計算,以產生一個數字。 例如:
1 - 1 // 0
#nan - #infinity // #nan
數字上的減法運算子 - 使用雙精確度;標準程式庫函式 Value.Subtract 可用來指定十進位精確度。 計算數字差時會發生下列情況:
雙精確度中差會根據 64 位元二進位雙精確度 IEEE 754 算術 IEEE 754-2008 的規則進行計算。 下表列出非零有限值、零、無限大和 NaN 所有可能組合的結果。 在下表中,
x和y是非零有限值,而z是x - y的結果。 如果x和y相等,則z為正零。 如果x - y太大,而無法以目的地類型表示,則z會是具有與x - y相同正負號的無限大。- y +0 0- +∞ -∞ NAN x z x x -∞ +∞ NAN +0 -y +0 +0 -∞ +∞ NAN -0 -y 0- +0 -∞ +∞ NAN +∞ +∞ +∞ +∞ NAN +∞ NAN -∞ -∞ -∞ -∞ -∞ NAN NAN NaN NAN NAN NAN NAN NAN NAN 計算十進位精確度的差,而不會失去精確度。 結果其小數位數大於兩個運算元的小數位數。
期間的差異
兩個期間差是以每個期間所代表 100 奈秒刻度數之間差所表示的期間。 例如:
#duration(1,2,30,0) - #duration(0,0,0,30.45)
// #duration(1, 2, 29, 29.55)
依據負期間位移後的日期時間
日期時間x 和期間 y 可能會使用 x - y 相減,以計算新的日期時間。 在這裡,「日期時間」 代表任何 date、datetime、datetimezone 或 time。 所產生「日期時間」與線性時間軸上 x 的距離會完全等於 y 的大小,但與 y 的正負號反向。 減去正期間會產生相對於 x 的時間倒流結果,而減去負值則會產生時間前流的結果。
#date(2010,05,20) - #duration(00,08,00,00)
//#datetime(2010, 5, 19, 16, 0, 0)
//2010-05-19T16:00:00
#date(2010,01,31) - #duration( 30,08,00,00)
//#datetime(2009, 12, 31, 16, 0, 0)
//2009-12-31T16:00:00
兩個日期時間之間的期間
兩個日期時間t 和 u 可能會使用 t - u 相減,以計算兩者之間的期間。 在這裡,「日期時間」 代表任何 date、datetime、datetimezone 或 time。 從 u 中減去 t 所產生的期間,必須在加上 t 後產生 u。
#date(2010,01,31) - #date(2010,01,15)
// #duration(16,00,00,00)
// 16.00:00:00
#date(2010,01,15)- #date(2010,01,31)
// #duration(-16,00,00,00)
// -16.00:00:00
#datetime(2010,05,20,16,06,00,-08,00) -
#datetime(2008,12,15,04,19,19,03,00)
// #duration(521,22,46,41)
// 521.22:46:41
當 t - u 產生負期間時,減去 u > t:
#time(01,30,00) - #time(08,00,00)
// #duration(0, -6, -30, 0)
使用 將兩個「日期時間」t - u相減時會發生下列情況:
- u + (t - u) = t
乘法運算子
乘法運算子 (x * y) 其解讀會相依於所評估運算式 x 和 y 的值類型,如下所示:
| X | Y | 結果 | 解釋 |
|---|---|---|---|
type number |
type number |
type number |
數值乘積 |
type number |
null |
null |
|
null |
type number |
null |
|
type duration |
type number |
type duration |
期間倍數 |
type number |
type duration |
type duration |
期間倍數 |
type duration |
null |
null |
|
null |
type duration |
null |
若不是表格中所列的值組合,則會引發原因代碼為 "Expression.Error" 的錯誤。 下列各節將說明每個組合。
評估任一運算式元時所引發的錯誤會進行傳播。
數值乘積
兩個數字的乘積是使用「乘法運算子」進行計算,以產生一個數字。 例如:
2 * 4 // 8
6 * null // null
#nan * #infinity // #nan
數字上的乘法運算子 * 使用雙精確度;標準程式庫函式 Value.Multiply 可用來指定十進位精確度。 計算數字乘積時會發生下列情況:
雙精確度中乘積會根據 64 位元二進位雙精確度 IEEE 754 算術 IEEE 754-2008 的規則進行計算。 下表列出非零有限值、零、無限大和 NaN 所有可能組合的結果。 在下表中,
x和y是正有限值。z是x * y的結果。 如果結果對目的地類型而言太大,則z為無限大。 如果結果對目的地類型而言太小,則z為零。* +y -y +0 0- +∞ -∞ NAN +x +z -z +0 0- +∞ -∞ NAN -x -z +z 0- +0 -∞ +∞ NAN +0 +0 0- +0 0- NAN NAN NAN -0 0- +0 0- +0 NAN NAN NAN +∞ +∞ -∞ NAN NAN +∞ -∞ NAN -∞ -∞ +∞ NAN NAN -∞ +∞ NAN NaN NAN NAN NAN NAN NAN NAN NAN 計算十進位精確度的乘積,而不會失去精確度。 結果其小數位數大於兩個運算元的小數位數。
期間的倍數
期間與數字的乘積是代表 100 奈秒刻度數的期間,以期間運算元乘以數字運算元表示。 例如:
#duration(2,1,0,15.1) * 2
// #duration(4, 2, 0, 30.2)
除法運算子
除法運算子 (x / y) 其解讀會相依於所評估運算式 x 和 y 的值類型,如下所示:
| X | Y | 結果 | 解釋 |
|---|---|---|---|
type number |
type number |
type number |
數值商 |
type number |
null |
null |
|
null |
type number |
null |
|
type duration |
type number |
type duration |
期間的分數 |
type duration |
type duration |
type number |
期間的數值商 |
type duration |
null |
null |
|
null |
type duration |
null |
若不是表格中所列的值組合,則會引發原因代碼為 "Expression.Error" 的錯誤。 下列各節將說明每個組合。
評估任一運算式元時所引發的錯誤會進行傳播。
數值商
兩個數字的商是使用「除法運算子」進行計算,以產生一個數字。 例如:
8 / 2 // 4
8 / 0 // #infinity
0 / 0 // #nan
0 / null // null
#nan / #infinity // #nan
數字上的除法運算子 / 使用雙精確度;標準程式庫函式 Value.Divide 可用來指定十進位精確度。 計算數字商時會發生下列情況:
雙精確度中商會根據 64 位元二進位雙精確度 IEEE 754 算術 IEEE 754-2008 的規則進行計算。 下表列出非零有限值、零、無限大和 NaN 所有可能組合的結果。 在下表中,
x和y是正有限值。z是x / y的結果。 如果結果對目的地類型而言太大,則z為無限大。 如果結果對目的地類型而言太小,則z為零。/ +y -y +0 0- +∞ -∞ NAN +x +z -z +∞ -∞ +0 0- NAN -x -z +z -∞ +∞ 0- +0 NAN +0 +0 0- NAN NAN +0 0- NAN -0 0- +0 NAN NAN 0- +0 NAN +∞ +∞ -∞ +∞ -∞ NAN NAN NAN -∞ -∞ +∞ -∞ +∞ NAN NAN NAN NaN NAN NAN NAN NAN NAN NAN NAN 計算十進位精確度的總和,而不會失去精確度。 結果其小數位數大於兩個運算元的小數位數。
期間的商
兩個期間商是以期間所代表 100 奈秒刻度數商表示的數字。 例如:
#duration(2,0,0,0) / #duration(0,1,30,0)
// 32
調整後的期間
期間 x 與數字 y 其商是代表 100 奈秒刻度數商的期間,以期間 x 與數字 y 表示。 例如:
#duration(2,0,0,0) / 32
// #duration(0,1,30,0)
結構組合
組合運算子 (x & y) 是透過下列類型的值所定義:
| X | Y | 結果 | 解釋 |
|---|---|---|---|
type text |
type text |
type text |
串連 |
type text |
null |
null |
|
null |
type text |
null |
|
type date |
type time |
type datetime |
合併 |
type date |
null |
null |
|
null |
type time |
null |
|
type list |
type list |
type list |
串連 |
type record |
type record |
type record |
合併 |
type table |
type table |
type table |
串連 |
串連
兩個文字、兩個清單或兩個資料表值可以使用 x & y 來串連。
下列範例說明如何串連文字值:
"AB" & "CDE" // "ABCDE"
下列範例說明如何串連清單:
{1, 2} & {3} // {1, 2, 3}
使用 x & y 串連兩個值時會發生下列情況:
評估
x或y運算式時所引發的錯誤會進行傳播。如果
x或y的項目包含錯誤,則不會傳播任何錯誤。串連兩個文字值的結果為文字值,其中包含 x 的值,後面緊接著 y。 如果其中一個運算元為 Null,另一個為文字值,則結果為 Null。
串連兩個清單的結果為清單,其中包含
x的所有項目,後面接著y的所有項目。串連兩個資料表的結果為資料表,其中具有兩個運算元資料表的資料行聯集。
x的資料行順序會保留下來,後面接著只出現在y中的資料行,並保留其相對順序。 對於只出現在其中一個運算元中的資料行,則會使用null填入另一個運算元的資料格值。
合併
記錄合併
您可使用 x & y 來合併兩個記錄,以產生一個記錄,其中包含來自 x 和 y 的欄位。
下列範例說明如何合併記錄:
[ x = 1 ] & [ y = 2 ] // [ x = 1, y = 2 ]
[ x = 1, y = 2 ] & [ x = 3, z = 4 ] // [ x = 3, y = 2, z = 4 ]
使用 x + y 來合併兩個記錄時會發生下列情況:
評估
x或y運算式時所引發的錯誤會進行傳播。如果欄位同時出現在
x和y中,則會使用來自y的值。所產生記錄中的欄位順序是
x的欄位順序,後面接著y中不屬於x的欄位,順序與其出現在y中的順序相同。合併記錄不會造成對值的評估。
因為欄位包含錯誤,所以不會引發錯誤。
結果會是一個記錄。
日期時間合併
可使用 x 將日期 y 與時間 x & y 合併,以產生結合 x 和 y 各部分的日期時間。
下列範例說明如何合併日期和時間:
#date(2013,02,26) & #time(09,17,00)
// #datetime(2013,02,26,09,17,00)
使用 x + y 來合併兩個記錄時會發生下列情況:
評估
x或y運算式時所引發的錯誤會進行傳播。結果會是日期時間。
一元運算子
+、- 和 not 運算子是一元運算子。
一元表達式:
型別表達式
+
一元運算式
-
一元運算式
not
一元運算式
一元加號運算子
一元加號運算子 (+x) 是透過下列類型的值所定義:
| X | 結果 | 解釋 |
|---|---|---|
type number |
type number |
一元加號 |
type duration |
type duration |
一元加號 |
null |
`null |
至於其他值,則會引發原因代碼為 "Expression.Error" 的錯誤。
一元加號運算子可供將 + 號套用至數字、日期時間或 Null 值。 結果會是相同的值。 例如:
+ - 1 // -1
+ + 1 // 1
+ #nan // #nan
+ #duration(0,1,30,0) // #duration(0,1,30,0)
評估一元加號運算子 +x 時會發生下列情況:
評估
x時所引發的錯誤會進行傳播。如果評估
x的結果不是數值,則會引發原因代碼為"Expression.Error"的錯誤。
一元減號運算子
一元減號運算子 (-x) 是透過下列類型的值所定義:
| X | 結果 | 解釋 |
|---|---|---|
type number |
type number |
否定 |
type duration |
type duration |
否定 |
null |
null |
至於其他值,則會引發原因代碼為 "Expression.Error" 的錯誤。
一元減號運算子可用來變更數字或期間的正負號。 例如:
- (1 + 1) // -2
- - 1 // 1
- - - 1 // -1
- #nan // #nan
- #infinity // -#infinity
- #duration(1,0,0,0) // #duration(-1,0,0,0)
- #duration(0,1,30,0) // #duration(0,-1,-30,0)
評估一元減號運算子 -x 時會發生下列情況:
評估
x時所引發的錯誤會進行傳播。如果運算式是數字,則結果會是運算式
x中正負號已變更的數值。 如果值為 NaN,則結果也會是 NaN。
邏輯否定運算子
邏輯否定運算子 (not) 是透過下列類型的值所定義:
| X | 結果 | 解釋 |
|---|---|---|
type logical |
type logical |
否定 |
null |
null |
此運算子會在指定的邏輯值上計算邏輯 not 運算。 例如:
not true // false
not false // true
not (true and true) // false
評估邏輯否定運算子 not x 時會發生下列情況:
評估
x時所引發的錯誤會進行傳播。評估運算式 x 所產生的值必須是邏輯值,否則必須引發原因代碼為
"Expression.Error"的錯誤。 如果值為true,則結果為false。 如果運算元為false,則結果為true。
結果會是邏輯值。
類型運算子
運算子 is 和 as 已知為類型運算子。
類型相容性運算子
類型相容性運算子 x is y 是針對下列類型的值所定義:
| X | Y | 結果 |
|---|---|---|
type any |
原始或可空原始型 | type logical |
x is y若所歸屬型x態與 y相容,則回傳true;若不相容則回傳false。
y 必須是原始型態或可空的原始型態。
is-expression:
as-expression
IS-表達is式原始型或可空原始型
原始型或可歸原原始型:
nullable
OPT 原始型
is 運算子所支援類型相容性是一般類型相容性的子集,且是使用下列規則所定義:
若
x為空,則若為型別any、型別null或可空的原始型態,則相容y。若
x非空,則若 的xy原始型與 相同,則相容。
評估運算式 x is y 時會發生下列情況:
- 評估運算式
x時所引發的錯誤會進行傳播。
類型判斷提示運算子
類型判斷提示運算子 x as y 是針對下列類型的值所定義:
| X | Y | 結果 |
|---|---|---|
type any |
原始或可空原始型 | type any |
運算式 x as y 會根據 x 運算子來判斷值 y 與 is 是否相容。 如果不相容,則會發生錯誤。
y 必須是原始型態或可空的原始型態。
as-expression:
equality-expression
作為表達as式原始或可歸還原始型
原始型或可歸原原始型:
nullable
OPT 原始型
運算式 x as y 的評估方式如下:
執行類型相容性檢查
x is y;如果該測試成功,則判斷提示會傳回未變更的x。如果相容性檢查失敗,則會引發原因代碼為
"Expression.Error"的錯誤。
範例:
1 as number // 1
"A" as number // error
null as nullable number // null
評估運算式 x as y 時會發生下列情況:
- 評估運算式
x時所引發的錯誤會進行傳播。
聯合運算子
聯合運算子 ?? 若不是 null,則會傳回其左運算元的結果,否則會傳回其右運算元的結果。 只有在左運算元是 null 時,才會評估右運算元。