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
)