Function
Function
Function.From
Function.From(functionType as type, function as function) as function
将仅支持单个list
类型形参的函数function
替换成支持多个形参的函数类型functionType
。
下面示例中,本来形参函数function
仅支持列表作为参数,但经过Function.From
处理后,结果函数支持多个值输入,而非仅一个列表。
Function.From(
type function (x as number, y as number, z as number) as number,
(x as list) as any => x
)(1, 2, "M")
Function.From(
type function (x as number, y as number, optional z as number) as number,
(x as list) as any => x
)(1, 2)
Function.Invoke
Function.Invoke(function as function, args as list) as any
根据给定的参数列表args
执行函数function
。
Function.Invoke((s as text, n as number) => Text.Repeat(s, n), {"ABC", 3})
Function.InvokeAfter
Function.InvokeAfter(function as function, delay as duration) as any
延迟delay
后执行函数function
。
Function.InvokeAfter(() => "hello world", #duration(0, 0, 0, 5))
Function.IsDataSource
Function.IsDataSource(function as function) as logical
判断函数function
是否是数据源。
Function.IsDataSource(() => "hello world")
Function.IsDataSource(Web.Contents)
Function.ScalarVector
Function.ScalarVector(
scalarFunctionType as type,
vectorFunction as function
) as function
返回scalarFunctionType
类型的标量函数,该函数调用带有单行参数的vectorFunction
函数并返回其单个输出。此外,当对输入表的每一行重复应用标量函数时,则仅对所有的输入应用一次vectorFunction
。
vectorFunction
将被传递一个表,其列的名称和位置与scalarFunctionType
相匹配。该表的每一行都包含调用标量函数的实参,列对应于scalarFunctionType
的参数。
vectorFunction
必须返回一个与输入表长度相同的列表(表行数与列项数相同)。其每个位置的项必须与相同位置的输入行上计算标量函数的结果相同。
输入表期望被流化,因此vectorFunction
期望在输入进入时对输出进行流化,一次仅处理一个输入块。特别是vectorFunction
不能多次枚举输入表。
解析
如下面的定义:
// fx
Function.ScalarVector(
type function (a as text, b as text),
(InputTable) => ...
)
该函数一参用于定义Table.AddColumn
中传入函数的参数,如定义上面的函数,则在Table.AddColumn
中应该传入fx([列1], [列2])
。
二参则用于实际调用,因为该函数实际只执行一次,因此文档中提到“不能多次枚举输入表”,如果在二参中多次调用输入表则会报错(不可多次访问行)。
在Table.AddColumn
中使用each fx([列1], [列2])
作为三参时,实际上InputTable
就是Table.AddColumn
一参的表,但该表仅包含传入的[列1]
和[列2]
,且表列名为a
、b
。
事实上,该函数的作用是通过将原本的遍历填充变为一次遍历所需的列,并输出与原表(即Table.AddColumn
一参的表)行数相同的项数,最终一次性填充到表列中。实际操作中,为了防止流计算,InputTable
必须使用Table.Buffer
。
一个完整的拼接的例子:
// fx
Function.ScalarVector(
type function (a as text, optional b as text, optional c as text) as text,
(InputTable) =>
let
Buffer = List.Buffer(Table.ToRows(InputTable)),
CallFunc = List.Transform(Buffer, each Text.Combine(_))
in
CallFunc
)
// 调用:Table.AddColumn(源, "自定义", each fx([A], [C]))
// 调用:Table.AddColumn(源, "自定义", each fx([A], [B], [C]))
注:
- 可以使用
optional
来让参数数量自适应。 - 因为上面表转成了列,因此使用了
List.Buffer
。
除了上述方式,还可以使用列表的形式:
// fx
Function.ScalarVector(
type function (a as text, optional b as any) as text,
(InputTable) =>
let
Buffer = List.Buffer(Table.ToRows(InputTable)),
CallFunc = List.Transform(Buffer, each _{1})
in
CallFunc
)
// 调用:Table.AddColumn(源, "自定义", each fx([A], [C]))
// 调用:Table.AddColumn(源, "自定义", each fx([A], {[B], [C]}))
当以列表形式fx([A], {[B], [C]})
传入时,输入表存储了两列,一列是a
,一列是b
,但b
列中存储源表B
和C
组成的列表。
示例1
下面的函数定义了对数字进行平方的查询(函数)
// Power2
(x as number) as number => x * x
下面在Table.AddColumn
中调用该方法:
Table.AddColumn(
#table({"Name", "Num"}, {{"Alic", 1}, {"Bob", 2}, {"Mike", 3}}),
"power2",
each Power2([Num])
)
在这种情况下,函数Power2
将会被调用3次。
将Power2
改成能够处理列表的ListPower2
函数:
// ListPower2
(x as list) as list => List.Transform(x, each _ * _)
使用Function.ScalarVector
对ListPower2
进行预处理,命名为scaleListPower2
:
// scaleListPower2
Function.ScalarVector(
type function (Num as number) as number,
(InputTable) =>
let
Buffer = Table.Buffer(InputTable),
NumList = Buffer[Num],
CallFunction = ListPower2(NumList)
in
CallFunction
)
添加列调用scaleListPower2
:
Table.AddColumn(
#table({"Name", "Num"}, {{"Alic", 1}, {"Bob", 2}, {"Mike", 3}}),
"power2",
each scaleListPower2([Num])
)
两种调用方式,虽然后者更加复杂和晦涩,但是后者仅调用一次就完成了整列的计算,对于支持批量查询的Web调用,该方法非常高效。
示例2
// 调用:Table.AddColumn(,, each fx([订单号], [金额])
Function.ScalarVector(
type function (OrderNum as number, Amount as number) as any,
(InputTable) =>
let
Buffer = List.Buffer(Table.ToRows(InputTable)),
CallFunction = List.Accumulate(
Buffer,
[preOrderNum = null, preAmount = null, resultList = {}],
(s, v) =>
[
preOrderNum = v{0},
preAmount = v{1},
resultList = s[resultList] & {
if (s[preOrderNum] = v{0}) and (s[preAmount] = v{1}) then "重复"
else "非重复"
}
]
)[resultList]
in
CallFunction
)