函式
「函式」是一種值,其代表從一組引數值到單一值的對應。 函式可以藉由提供的一組輸入值 (引數值) 叫用,並產生單一輸出值 (傳回值)。
撰寫函式
函式是使用 function-expression 撰寫的:
function-expression:
(
parameter-listopt )
function-return-typeopt =>
function-body
function-body:
expression
parameter-list:
fixed-parameter-list
fixed-parameter-list ,
optional-parameter-list
optional-parameter-list
fixed-parameter-list:
parameter
parameter ,
fixed-parameter-list
參數:
parameter-name parameter-typeopt
parameter-name:
identifier
parameter-type:
assertion
function-return-type:
assertion
assertion:
as
nullable-primiitve-type
optional-parameter-list:
optional-parameter
optional-parameter ,
optional-parameter-list
optional-parameter:
optional
參數
nullable-primitve-type
nullable
opt primitive-type
下列是函式的範例,該函式需要兩個值 x
和 y
,並會產生將 +
運算子套用到這些值的結果。 x
和 y
是屬於函式 parameter-list 的「參數」,而 x + y
則是 function-body:
(x, y) => x + y
評估 function-expression 的結果是產生函式值 (而非評估 function-body)。 作為此文件中的慣例,函式值 (與函式運算式相對) 會與 parameter-list 一同顯示,但 function-body 則會顯示為省略符號 (...
)。 例如,一旦評估了以上的函式運算式,便會顯示為下列函式值:
(x, y) => ...
其中已為函式值定義下列運算子:
運算子 | 結果 |
---|---|
x = y |
等於 |
x <> y |
不等於 |
函式值的原生類型是自訂函式類型 (衍生自內建類型 function
),該類型會列出參數名稱和指定所有參數類型及傳回類型為 any
。 (請移至函式類型以取得函式類型的詳細資料。)
叫用函式
函式的 function-body 會透過使用 invoke-expression「叫用」函式值來執行。 叫用函式值表示函式值的 function-body 會經過評估,並傳回值或引發錯誤。
invoke-expression:
primary-expression (
argument-listopt )
argument-list:
expression-list
每次叫用函式值時,都會將一組值指定為 argument-list,稱為傳至函式的「引數」。
argument-list 會用來將固定數量的引數直接指定為運算是清單。 下列範例會定義一個記錄,其欄位中包含一個函式值,然後從記錄的另一個欄位叫用函式:
[
MyFunction = (x, y, z) => x + y + z,
Result1 = MyFunction(1, 2, 3) // 6
]
叫用函式時適用下列項目:
用來評估函式 function-body 的環境包含一個變數,該變數對應至每個參數,且名稱與參數相同。 每個參數值都對應至從 invoke-expression 的 argument-list 建構的值,如參數中所定義。
對應至函式引數的所有運算式都會在評估 function-body 前先行評估。
評估 expression-list 或 function-body 中運算式時引發的錯誤會進行散佈。
從 argument-list 所建構引數數量必須與函式的參數相容,否則會引發原因代碼為
"Expression.Error"
的錯誤。 判斷相容性的流程會定義在參數中。
參數
有兩種參數可能會呈現在 parameter-list 中:
「必要」參數指出對應至參數的引數一律必須在叫用函式時指定。 首先,必須在 parameter-list 中指定必要參數。 下列範例中的函式會定義必要參數
x
和y
:[ MyFunction = (x, y) => x + y, Result1 = MyFunction(1, 1), // 2 Result2 = MyFunction(2, 2) // 4 ]
「選擇性」參數指出對應至參數的引數可以在叫用函式時指定,但並非一定要指定。 若在叫用函式時沒有指定對應至選擇性參數的引數,則會使用
null
值。 選用參數必須出現在 parameter-list 中任何必要參數之後。 下列範例中的函式會定義一個固定參數x
,和一個選擇性參數y
:[ MyFunction = (x, optional y) => if (y = null) x else x + y, Result1 = MyFunction(1), // 1 Result2 = MyFunction(1, null), // 1 Result3 = MyFunction(2, 2), // 4 ]
叫用函式時指定的引數數量必須與參數清單相容。 函式 F
一組引數 A
的相容性會透過如下方式計算:
令 N 值代表從 argument-list 建構的引數
A
數量。 例如:MyFunction() // N = 0 MyFunction(1) // N = 1 MyFunction(null) // N = 1 MyFunction(null, 2) // N = 2 MyFunction(1, 2, 3) // N = 3 MyFunction(1, 2, null) // N = 3 MyFunction(1, 2, {3, 4}) // N = 3
令 Required 代表固定參數
F
的數量,並令 Optional 代表F
選擇性參數的數量。 例如:() // Required = 0, Optional = 0 (x) // Required = 1, Optional = 0 (optional x) // Required = 0, Optional = 1 (x, optional y) // Required = 1, Optional = 1
若下列為 true,則引數
A
與函式F
相容:- (N >= Fixed) 且 (N <= (Fixed + Optional))
- 引數類型與
F
的對應參數類型相容
若函式具備宣告的傳回類型,則若下列為 true,函式
F
主體結果值便與F
的傳回類型相容:- 使用為函式參數提供的引數來評估函式主體所產生值,其具備與傳回類型相容的類型。
若函式主體所產生值與函式的傳回類型不相容,則會引發原因代碼為
"Expression.Error"
的錯誤。
遞迴函式
若要撰寫遞迴函式值,則必須使用範圍運算子 (@
) 來在函式的範圍內參考函式。 例如,下列記錄包含一個欄位,其定義 Factorial
函式,以及另一個呼叫該函式的欄位:
[
Factorial = (x) =>
if x = 0 then 1 else x * @Factorial(x - 1),
Result = Factorial(3) // 6
]
同樣地,您也可以撰寫相互遞迴的函式,只要需要存取的每個函式都具備名稱即可。 在下列範例中,Factorial
函式的一部分已重構至第二個 Factorial2
函式。
[
Factorial = (x) => if x = 0 then 1 else Factorial2(x),
Factorial2 = (x) => x * Factorial(x - 1),
Result = Factorial(3) // 6
]
結束
函式可以傳回另一個函式作為值。 此函式接著可以相依於原始函式的一或多個參數。 在下列範例中,與欄位 MyFunction
建立關聯的函式會傳回函式,該函式則會傳回指定給其的參數:
[
MyFunction = (x) => () => x,
MyFunction1 = MyFunction(1),
MyFunction2 = MyFunction(2),
Result = MyFunction1() + MyFunction2() // 3
]
每次叫用函式時,都會傳回保留參數值的新函式值,因此每當叫用時,都會傳回參數值。
函式和環境
除了參數外,function-expression 的 function-body 可以在初始化函式時參考環境中存在的變數。 例如,欄位 MyFunction
所定義函式會存取封入記錄 A
的欄位 C
:
[
A =
[
MyFunction = () => C,
C = 1
],
B = A[MyFunction]() // 1
]
叫用 MyFunction
時,其會存取變數 C
的值,即使是從並未包含變數 C
的環境 (B
) 中叫用該函式也一樣。
簡化的宣告
each-expression 是一種語法速記,用來宣告接受名為 _
(底線) 單一參數的無類型函式。
each-expression:
each
each-expression-body
each-expression-body:
function-body
經簡化宣告經常用來改善高階函式引動的可讀性。
例如,下列宣告對在語意上是相等的:
each _ + 1
(_) => _ + 1
each [A]
(_) => _[A]
Table.SelectRows( aTable, each [Weight] > 12 )
Table.SelectRows( aTable, (_) => _[Weight] > 12 )