閱讀英文

共用方式為


運算子行為

本節定義各種 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 邏輯否定
中繼資料 xmetay 關聯中繼資料
乘法 x * y 乘法
x / y 部門
加法 x + y 加法
x - y
關聯式 x< y 小於
x > y 大於
x<= y 小於或等於
x >= y 大於或等於
Equality x = y 等於
x<> y 不等於
類型判斷提示 xasy 為相容、可為 Null 的基本類型或錯誤
類型一致性 xisy 測試是否為相容、可為 Null 的基本類型
邏輯 AND xandy 最少運算結合
邏輯 OR xory 最少運算分離
Coalesce x??y Null 聯合運算子

運算子和中繼資料

每個值都有相關聯的記錄值,可包含該值的其他資訊。 此記錄稱為值的「中繼資料記錄」。 中繼資料記錄可以與任何類型的值建立關聯,甚至是 null。 這類關聯結果就是具有指定中繼資料的新值。

中繼資料記錄只是一般記錄,可以包含一般記錄所能包含的任何欄位和值,且本身就有中繼資料記錄。 建立中繼資料記錄與值的關聯「不會造成干擾」。 不會在評估時變更值的行為,但明確檢查中繼資料記錄的評估則除外。

每個值都有預設中繼資料記錄,即使尚未指定一個也一樣。 預設中繼資料記錄為空白。 下列範例說明如何使用 Value.Metadata 標準程式庫函式來存取文字值的中繼資料記錄:

Value.Metadata( "Mozart" )   // []

若搭配建構新值的運算子或函式使用值,通常「不會保留」中繼資料記錄。 例如,若使用 & 運算子將兩個文字值串連,則所產生文字值的中繼資料會是空白記錄 []。 下列運算式是對等的:

"Amadeus " & ("Mozart" meta [ Rating = 5 ])  
"Amadeus " & "Mozart"

標準程式庫函式 Value.RemoveMetadataValue.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} 時會發生下列情況:

  • 評估運算式 xy 期間所引發的錯誤會進行傳播。

  • 運算式 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 值。

在欄位存取的過程中,只會評估 xy 所命名的欄位。

中繼資料運算子

您可使用「meta 運算子」(x meta y) 來修改值的中繼資料記錄。

metadata-expression:
      unary-expression
      unary-expression
metaunary-expression

下列範例會使用 meta 運算子來建構具有中繼資料記錄的文字值,然後使用 Value.Metadata 來存取所產生值的中繼資料記錄:

Value.Metadata( "Mozart" meta [ Rating = 5 ] ) 
// [Rating = 5 ]
Value.Metadata( "Mozart" meta [ Rating = 5 ] )[Rating] 
// 5

套用結合運算子 x meta y 的中繼資料時會發生下列情況:

  • 評估 xy 運算式時所引發的錯誤會進行傳播。

  • y 運算式必須是記錄,否則會引發原因代碼為 "Expression.Error" 的錯誤。

  • 所產生中繼資料記錄是與 x 合併的 y 中繼資料記錄 (如需記錄合併的語意,請參閱記錄合併)。

  • 所產生值是來自 x 運算式的值,不含其中繼資料,而是附加新計算的中繼資料記錄。

標準程式庫函式 Value.RemoveMetadataValue.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 = yx <> y 時會發生下列情況:

  • 評估 xy 運算式時所引發的錯誤會進行傳播。

  • 如果值相等,則 = 運算子的結果為 true;否則為 false

  • 如果值相等,則 <> 運算子的結果為 false;否則為 true

  • 中繼資料記錄不會包含在比較中。

  • 如果評估 xy 運算式所產生值不是相同類型的值,則值不相等。

  • 如果評估 xy 運算式所產生值是相同類型的值,則會透過特定規則來判斷是否相等,如下所定義。

  • 下列條件一律成立:

    (x = y) = not (x <> y)

等號比較運算子是針對下列類型所定義:

  • null 值只等於其本身。
    null = null    // true 
    null = true    // false 
    null = false   // false
  • 邏輯值 truefalse 只等於其本身。 例如:
    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

評估包含關係運算子的運算式時會發生下列情況:

  • 評估 xy 運算元運算式時所引發的錯誤會進行傳播。

  • 評估 xy 運算式所產生的值必須是二進位、日期、日期時間、日期時區、期間、邏輯、數字、Null、文字或時間值。 否則,就會引發原因代碼為 "Expression.Error" 的錯誤。

  • 這兩個運算元都必須是相同種類的值或 null。 否則,就會引發原因代碼為 "Expression.Error" 的錯誤。

  • 如果其中一或兩個運算元為 null,則結果為 null 值。

  • 兩個二進位會逐個位元組進行比較。

  • 兩個日期的比較方式是先比較其年部分;若相等,則比較其月部分;若相等,則比較其日部分。

  • 兩個日期時間的比較方式是先比較其年部分;若相等,則比較其月部分;若相等,則比較其日部分;若相等,則比較其小時部分;若相等,則比較其分鐘部分;若相等,則比較其秒部分。

  • 兩個日期時區的比較方式是先藉由減去其小時/分鐘位移來將其正規化為 UTC,再比較其日期時間元件。

  • 兩個持續時間會根據其所代表的 100 奈秒刻度總數來進行比較。

  • 兩個邏輯會進行比較,使得 true 被視為大於 false

  • 兩個數字 xy 會根據 IEEE 754 標準的規則進行比較:

    • 如果任一個運算元為 #nan,則所有關係運算子的結果都為 false

    • 當運算元都不是 #nan 時,運算子會根據排序 -∞ < -max < ... < -min < -0.0 = +0.0 < +min < ... < +max < +∞ 比較兩個浮點運算元,其中 min 和 max 是可以表示的最小和最大正有限值。 -∞ 和 +∞ 的 M 名稱是 -#infinity#infinity

      此順序值得注意的影響如下:

      • 負零和正零會視為相等。

      • -#infinity 值會視為小於其他所有數值,但等於另一個 -#infinity

      • #infinity 值會視為大於其他所有數值,但等於另一個 #infinity

  • 兩個文字的比較方式是使用逐字元序數、區分大小寫、不區分文化特性的比較。

  • 兩個時間的比較方式是先比較其小時部分;若相等,則比較其分鐘部分;若相等,則比較其秒部分。

條件邏輯運算子

andor 運算子稱為條件邏輯運算子。

logical-or-expression:
      logical-and-expression
logical-and-expression
orlogical-or-expression
logical-and-expression:
      is-expression
      is-expression
andlogical-and-expression

當至少有一個運算元為 or 時,true 運算子會傳回 true。 只有在左運算元不是 true 時,才會評估右運算元。

當至少有一個運算元為 and 時,false 運算子會傳回 false。 只有在左運算元不是 false 時,才會評估右運算元。

以下顯示 orand 運算子的事實資料表,其中包含評估垂直軸上左運算元運算式的結果,以及評估水平軸上右運算元運算式的結果。

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

評估包含條件邏輯運算子的運算式時會發生下列情況:

  • 評估 xy 運算式時所引發的錯誤會進行傳播。

  • 條件邏輯運算子是透過 logicalnull 類型所定義。 如果運算元的值不是這些類型,則會引發原因代碼為 "Expression.Error" 的錯誤。

  • 結果會是邏輯值。

  • 在運算式 xy 中,只有在 y 未評估為 x 時,才會評估運算式 true

  • 在運算式 xy 中,只有在 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.AddValue.SubtractValue.MultiplyValue.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 datetype datetimetype datetimezonetype time 的任何一種。 當某個「日期時間」類型的期間和值相加時,所產生值會是相同的類型。

若不是表格中所列的值組合,則會引發原因代碼為 "Expression.Error" 的錯誤。 下列各節將說明每個組合。

評估任一運算式元時所引發的錯誤會進行傳播。

數值總和

兩個數字的總和是使用「加法運算子」進行計算,以產生一個數字。

例如:

1 + 1             // 2 
#nan + #infinity  // #nan

數字上的加法運算子 + 使用雙精確度;標準程式庫函式 Value.Add 可用來指定十進位精確度。 計算數字總和時會發生下列情況:

  • 雙精確度中總和會根據 64 位元二進位雙精確度 IEEE 754 算術 IEEE 754-2008 的規則進行計算。 下表列出非零有限值、零、無限大和 NaN 所有可能組合的結果。 在下表中,xy 是非零有限值,而 zx + y 的結果。 如果 xy 具有相同的大小,但正負號相反,則 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 的大小。 在這裡,「日期時間」代表任何 DateDateTimeDateTimeZoneTime,而非 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) 其解讀會相依於所評估運算式 xy 的值類型,如下所示:

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 datetype datetimetype datetimezonetype time 的任何一種。 從某個「日期時間」類型的值中減去期間時,所產生值會是相同的類型。

若不是表格中所列的值組合,則會引發原因代碼為 "Expression.Error" 的錯誤。 下列各節將說明每個組合。

評估任一運算式元時所引發的錯誤會進行傳播。

數值差

兩個數字之間的差是使用「減法運算子」進行計算,以產生一個數字。 例如:

1 - 1                // 0 
#nan - #infinity     // #nan

數字上的減法運算子 - 使用雙精確度;標準程式庫函式 Value.Subtract 可用來指定十進位精確度。 計算數字差時會發生下列情況:

  • 雙精確度中差會根據 64 位元二進位雙精確度 IEEE 754 算術 IEEE 754-2008 的規則進行計算。 下表列出非零有限值、零、無限大和 NaN 所有可能組合的結果。 在下表中,xy 是非零有限值,而 zx - y 的結果。 如果 xy 相等,則 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 相減,以計算新的日期時間。 在這裡,「日期時間」 代表任何 datedatetimedatetimezonetime。 所產生「日期時間」與線性時間軸上 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

兩個日期時間之間的期間

兩個日期時間tu 可能會使用 t - u 相減,以計算兩者之間的期間。 在這裡,「日期時間」 代表任何 datedatetimedatetimezonetime。 從 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 所有可能組合的結果。 在下表中,xy 是正有限值。 zx * 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) 其解讀會相依於所評估運算式 xy 的值類型,如下所示:

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 所有可能組合的結果。 在下表中,xy 是正有限值。 zx / 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 串連兩個值時會發生下列情況:

  • 評估 xy 運算式時所引發的錯誤會進行傳播。

  • 如果 xy 的項目包含錯誤,則不會傳播任何錯誤。

  • 串連兩個文字值的結果為文字值,其中包含 x 的值,後面緊接著 y。 如果其中一個運算元為 Null,另一個為文字值,則結果為 Null。

  • 串連兩個清單的結果為清單,其中包含 x 的所有項目,後面接著 y 的所有項目。

  • 串連兩個資料表的結果為資料表,其中具有兩個運算元資料表的資料行聯集。 x 的資料行順序會保留下來,後面接著只出現在 y 中的資料行,並保留其相對順序。 對於只出現在其中一個運算元中的資料行,則會使用 null 填入另一個運算元的資料格值。

合併

記錄合併

您可使用 x & y 來合併兩個記錄,以產生一個記錄,其中包含來自 xy 的欄位。

下列範例說明如何合併記錄:

[ x = 1 ] & [ y = 2 ]                // [ x = 1, y = 2 ] 
[ x = 1, y = 2 ] & [ x = 3, z = 4 ]  // [ x = 3, y = 2, z = 4 ]

使用 x + y 來合併兩個記錄時會發生下列情況:

  • 評估 xy 運算式時所引發的錯誤會進行傳播。

  • 如果欄位同時出現在 xy 中,則會使用來自 y 的值。

  • 所產生記錄中的欄位順序是 x 的欄位順序,後面接著 y 中不屬於 x 的欄位,順序與其出現在 y 中的順序相同。

  • 合併記錄不會造成對值的評估。

  • 因為欄位包含錯誤,所以不會引發錯誤。

  • 結果會是一個記錄。

日期時間合併

可使用 x 將日期 y 與時間 x & y 合併,以產生結合 xy 各部分的日期時間。

下列範例說明如何合併日期和時間:

#date(2013,02,26) & #time(09,17,00) 
// #datetime(2013,02,26,09,17,00)

使用 x + y 來合併兩個記錄時會發生下列情況:

  • 評估 xy 運算式時所引發的錯誤會進行傳播。

  • 結果會是日期時間。

一元運算子

+-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

結果會是邏輯值。

類型運算子

運算子 isas 已知為類型運算子。

類型相容性運算子

類型相容性運算子 x is y 是針對下列類型的值所定義:

X Y 結果
type any nullable-primitive-type type logical

如果 x is y 的歸屬類型與 true 相容,則運算式 x 會傳回 y;如果 false 的歸屬類型與 x 不相容,則傳回 yy 必須是 nullable-primitivetype

is-expression:
      as-expression
      is-expression
isnullable-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 運算子來判斷值 yis 是否相容。 如果不相容,則會發生錯誤。 y 必須是 nullable-primitive-type

as-expression:
      equality-expression
      as-expression
asnullable-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 時,才會評估右運算元。