首页 > 解决方案 > 如何在 Lua 函数上应用元表以启用它们之间的自定义运算符?

问题描述

我正在尝试在特定功能上设置一个元表,以启用自定义运算符以在它们之间进行功能组合。

我想在我的库中引入组合运算符的原因是因为我不想像这样将参数括号嵌套到另一个中:f(g(h(x)))而是:f * g * h(x),或者类似不需要嵌套括号的东西。

到目前为止,我有两种方法来实现我的目标:

  1. 尝试__mul为 Lua 函数设置元方法,我不确定具体如何。

  2. __call通过为和提供元方法,通过元表将所有可组合函数重新定义为可调用的功能组合表__mul

我今天为第二种方法(功能复合表)编写了一个实验(和一个工作)实现。但我不认为它很优雅,它更像是一种 hack,在内存和处理方面的开销很大,只是语法糖。它非常复杂,以至于它有自己的调用堆栈队列,因为 Lua 评估自定义运算符左关联,而功能组合实际上是右关联(当我实现它时我错误地这么认为,结果证明它是必要的,原因完全不同。参见在评论中)。

我目前使用函数和元表实现第一种方法的尝试如下所示:

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 表和字符串。

标签: lua

解决方案


虽然所有 Lua 值都可以有元表,setmetatable 但只能为表设置元表。表和完整的用户数据可以在单个值上设置元表,而不同类型的值都为每种类型共享一个元表。例如,所有字符串都具有相同的元表。

所以你不能为一个函数设置一个元表,但你可以为所有函数设置一个元表。只有debug图书馆才能做到这一点,通过debug.setmetatable. 同样,这将适用于任何地方的所有功能


推荐阅读