訓練
運算子行為
本節定義各種 M 運算子的行為。
當運算式包含多個運算子時,運算子的「優先順序」會控制評估個別運算子的順序。 例如,運算式 x + y * z
會評估為 x + (y * z)
,因為 *
運算子的優先順序高於二元 +
運算子。 運算子優先順序是由其相關聯文法結果的定義所建立。 例如,「加法類運算式」是由 或 +
運算子分隔的「乘法類運算式」-
序列所組成,因此 +
和 -
運算子的優先順序會低於 *
和 /
運算子。
「加括弧的運算式」結果可用來變更預設優先順序。
parenthesized-expression:
(
運算式)
例如:
1 + 2 * 3 // 7
(1 + 2) * 3 // 9
下表摘要說明 M 運算子,並依序 (從最高優先順序到最低優先順序) 列出運算子類別。 相同分類中的運算子具有相等的優先順序。
類別 | 運算式 | 描述 |
---|---|---|
Primary |
i @ i |
識別碼運算式 |
(x) | 加括弧的運算式 | |
x[i] | 查閱 | |
x{y} | 項目存取 | |
x(...) | 函式引動過程 | |
{x, y, ...} | 清單初始化 | |
[ i = x, ... ] | 記錄初始化 | |
... | 未實作 | |
一元 | + x | 身分識別 |
- x | 否定 | |
not
x |
邏輯否定 | |
中繼資料 |
xmeta y |
關聯中繼資料 |
乘法 | x * y | 乘法 |
x / y | 部門 | |
加法 | x + y | 加法 |
x - y | 減 | |
關聯式 | x< y | 小於 |
x > y | 大於 | |
x<= y | 小於或等於 | |
x >= y | 大於或等於 | |
Equality | x = y | 等於 |
x<> y | 不等於 | |
類型判斷提示 |
xas y |
為相容、可為 Null 的基本類型或錯誤 |
類型一致性 |
xis y |
測試是否為相容、可為 Null 的基本類型 |
邏輯 AND |
xand y |
最少運算結合 |
邏輯 OR |
xor y |
最少運算分離 |
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-access-expression:
item-selection
optional-item-selection
item-selection:
primary-expression{
item-selector}
optional-item-selection:
primary-expression{
item-selector} ?
item-selector:
expression
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:
primary-expression field-selector
field-selector:
required-field-selector
optional-field-selector
required-field-selector:
[
field-name]
optional-field-selector:
[
field-name] ?
field-name:
generalized-identifier
quoted-identifier
implicit-target-field-selection:
field-selector
projection:
primary-expression required-projection
primary-expression optional-projection
required-projection:
[
required-selector-list]
optional-projection:
[
required-selector-list] ?
required-selector-list:
required-field-selector
required-selector-list,
required-field-selector
implicit-target-projection:
required-projection
optional-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
unary-expressionmeta
unary-expression
下列範例會使用 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)
等號比較運算子=
用來判斷兩個值是否相等。
不等比較運算子<>
用來判斷兩個值是否不相等。
equality-expression:
relational-expression
relational-expression=
equality-expression
relational-expression<>
equality-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
函式值等於其本身,但不一定等於另一個函式值。 如果兩個函式值視為相等,則在叫用時會有相同的行為。
兩個指定的函式值一律會有相同等號比較關係。
類型值等於其本身,但不一定等於另一個類型值。 如果兩個類型值視為相等,則在查詢一致性時會有相同的行為。
兩個指定的類型值一律會有相同等號比較關係。
<
、>
、<=
和 >=
運算子稱為「關係運算子」。
relational-expression:
additive-expression
additive-expression<
relational-expression
additive-expression>
relational-expression
additive-expression<=
relational-expression
additive-expression>=
relational-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
運算子稱為條件邏輯運算子。
logical-or-expression:
logical-and-expression
logical-and-expressionor
logical-or-expression
logical-and-expression:
is-expression
is-expressionand
logical-and-expression
當至少有一個運算元為 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
+
、-
、*
和 /
運算子是「算術運算子」。
additive-expression:
multiplicative-expression
additive-expression+
multiplicative-expression
additive-expression-
multiplicative-expression
multiplicative-expression:
metadata-expression
multiplicative-expression*
metadata-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
運算子是一元運算子。
unary-expression:
type-expression
+
一元運算式
-
一元運算式
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 |
nullable-primitive-type | type logical |
如果 x is y
的歸屬類型與 true
相容,則運算式 x
會傳回 y
;如果 false
的歸屬類型與 x
不相容,則傳回 y
。
y
必須是 nullable-primitivetype。
is-expression:
as-expression
is-expressionis
nullable-primitive-type
nullable-primitive-type:
nullable
opt primitive-type
is
運算子所支援類型相容性是一般類型相容性的子集,且是使用下列規則所定義:
當
x
為 null 時,如果y
為類型any
、類型null
或可為 null 的類型,則其相容。如果
x
為非 Null,則會在x
的基本類型與y
相同時相容。
評估運算式 x is y
時會發生下列情況:
- 評估運算式
x
時所引發的錯誤會進行傳播。
類型判斷提示運算子 x as y
是針對下列類型的值所定義:
X | Y | 結果 |
---|---|---|
type any |
nullable-primitive-type | type any |
運算式 x as y
會根據 x
運算子來判斷值 y
與 is
是否相容。 如果不相容,則會發生錯誤。
y
必須是 nullable-primitive-type。
as-expression:
equality-expression
as-expressionas
nullable-primitive-type
運算式 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 時,才會評估右運算元。