我可以将一个函数注入到 Lua 函数中吗?
如果我有这个 lua 函数:
function dostuff(x)
function foo () x=x+1; end
foo();
return x;
end
结果是我需要多次使用 foo。但它主要有用是因为它可以访问 x upvalue。有没有一种方法将 foo 移出 dostuff,但仍然让它访问 x?
我尝试将 foo() 全局化并添加到 dostuff 中,像这样:
function foo () x=x+1; end
function dostuff(x)
foo();
return x;
end
dostuff.foo = foo
但由于在 lua 中函数与表不同(与 js 不同),因此此方法无效。我仍然觉得这在 lua 中可以实现,可能需要使用元表。但我对此了解不够。我知道有很多方法可以避免这种情况并绕过它。我只是好奇是否有一种方法可以做到这一点。
也许另一种方法是,您可以使用闭包选择调用全局函数。
由于您只提供了一个粗略的例子而没有实际使用情况,因此建议替代方案有些困难。首先,对我而言,这就像您想要做的事情:
local x;
function foo() x=x+1 end
function dostuff(a)
x = a;
foo();
return x;
end
我的问题在于,foo非常简单,没有理由不将其作为带有参数 x 和返回值 x+1 的函数。此外,虽然 x 的必要初始化步骤不是很糟糕,而且不会立即导致任何错误,但是当您必须为另一个函数初始化变量时,它会使开发有些奇怪,并且如果您不这样做可能会创建一个调试地狱。
因此,由于 Lua 还支持多返回值,上面的代码实际上是一个坏点子,不会给您带来任何好处:
function foo(a,b,c) return a,b,c end
function dostuff()
a,b,c = foo(a,b,c);
end
由于您写了关于代码重用的内容,这里提供了一个一般性的技巧,即利用闭包:
您可以调整结构,使 foo 不接受 x 为参数,而是使 dostuff 接受 foo 作为参数:
function dostuff(foo)
return foo()
end
dostuff(function() return 1 end)
dostuff(function() return 2 end)
进一步推广会带您到一种称为 partial application 的技术:
function dostuff(foo)
return function(x)
return foo(x);
end
end
dostuff(function(x) return x+1 end)(17)
local f = dostuff(function(x) return x+1 end)
f(17)f(18)f(19) -- ...
现在,这意味着您不仅可以从外部修改函数内部的工作方式,还可以保存该状态。作为额外的奖励,还可以将一次“实例”中只需执行一次的昂贵操作放在外部函数中,并节省一些性能。
希望这些想法足以帮助您解决代码重用的问题 ;)
你想要的是动态作用域。不幸的是,Lua 不支持动态作用域。它支持的是词法作用域。在 JavaScript 中,你可以使用 eval 模拟动态作用域,但 Lua 没有 eval。
最后的方法是使用继承。我通常在 Lua 中使用一个名为 extend 的函数来实现继承,它类似于 JavaScript 中的 Object.create 函数:
local o = {}
function o:extend(table)
return setmetatable(table, {
__index = self
})
end
使用这种方法,我现在可以创建一个对象来实现动态作用域:
local dynamic = o:extend {}
function dynamic:foo()
self.x = self.x + 1
end
方法 foo 是动态作用域的,因为它的变量 x 没有指向任何特定的值。它取决于 self 的值,而 self 的值是可以改变的。我们可以这样使用它:
function dostuff(x)
local scope = dynamic:extend {
x = x
}
scope:foo()
return scope.x
end
但是,与其每次执行 dostuff 都创建一个新的 scope,不如简单地这样做:
local myscope = dynamic:extend {}
function myscope:dostuff(x)
self.x = x
self:foo()
return self.x
end
实际上,如果您决定像上面所示那样重构代码,甚至不需要继承。你所需要做的就是:
local myscope = {}
function myscope:foo()
self.x = self.x + 1
end
function myscope:dostuff(x)
self.x = x
self:foo()
return self.x
end
唯一的区别是现在你需要调用 myscope:dostuff 而不是直接调用 dostuff。但这是一件好事,因为你不会污染全局作用域。
这是我会做的方式,也是我建议你采用的方式。所有 Lua 标准库函数也都是在对象上定义的。
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
一个更清晰,更干净的方式是只将参数传递给
foo,我建议你使用这种方法。另一种方法是使用全局变量或局部变量(即模块或块内)对所有相关函数进行公用。
否则,我没找到任何其他的方法。我建议重新设计你的方法。