【发布时间】:2019-08-03 13:16:01
【问题描述】:
我正在尝试为特定函数设置一个元表,以启用自定义运算符以在它们之间进行函数组合。
我想在我的库中引入组合运算符的原因是因为我不想像这样将参数括号嵌套到另一个括号中:f(g(h(x))),而是:f * g * h(x),或者类似的东西不会需要嵌套括号。
到目前为止,我有两种方法可以实现我的目标:
尝试为 Lua 函数设置
__mul元方法,我不确定具体如何。通过为
__call和__mul提供元方法,通过元表将所有可组合函数重新定义为可调用的功能组合表。
我为今天的第二种方法(功能复合表)写了一个实验(和一个工作)implementation。但我不认为它很优雅,它更像是一种 hack,在内存和处理方面的开销很大,只是语法糖。它是如此复杂以至于它有自己的调用堆栈队列,因为 Lua 评估自定义运算符左关联 而功能组合实际上是右关联(我在实现时错误地认为是这样,结果证明是必要的完全不同的原因。见 cmets)。
我目前使用函数和元表实现第一种方法的尝试如下所示:
local compositable =
{
__mul = function(a, b)
a(b)
end
}
local function f(x) return x*x end
local function g(x) return -x end
setmetatable(f, compositable) -- Error, table expected, got function.
setmetatable(g, compositable) -- "
local result = f * g(4)
print(result) -- Expected result: -16
但这不起作用,似乎只有 Lua 表和字符串才允许使用 Lua 中的元表设置。
【问题讨论】:
-
根据Wikipedia,函数组合是关联的,所以不需要使
__mul右关联。 -
@luther,哎呀。对不起,我会纠正这个。然而事实证明,出于不同的原因,我必须将此运算符实现为右关联(因为这样底层函数将从尚未评估的左侧复合表接收,而不是用于计算的实际数值)。今晚我会尝试更深入地研究这个并再次检查我的代码,看看我是否可以在没有右关联的情况下重新实现它。
-
因此,您实际上是在尝试通过在函数调用之前评估
*来更改运算符优先级。我建议像(f * g)(x)这样调用。更改运算符优先级可能会违反有关语法的基本假设,从而使代码难以阅读。请注意,您并不总是需要括号,因为您不会总是立即调用新函数。将组合函数存储到变量或将其作为参数传递是很常见的,就像匿名函数一样。
标签: lua