如何使用Lua中的__call创建DSL,在其中实现子节?
我不熟悉lua,正在尝试创建一个配置DSL,它允许具有默认值的部分。
因此,java表格是预定义的,具有许多值
“`Java = { Source = 1.6, 目标=1.6, 目录={ 源头="src/main/java", 输出="build/classes", }, }“
我有一个Config原型,实现了__call,因此,当将其作为带表构造函数的函数调用时,它仅覆盖默认值。类似于此:
“Config.__call = function(t, props) for k,v in pairs(props) do t[k] = v end end“
这个想法是你只能调用dsl来指定你想要覆盖的内容:
“Java={ Source = 1.5, 目录{ 源码="customsrcdir", } }“
存在一个Config.new方法,可以递归应用原型到表格上,从而使所有元表都具有设置__call方法的元表。
我的问题是“目录”子节。它在全局上下文中评估,因此唯一的方法使其工作是:
“Java={ Source = 1.5, Java.directories{ 源码="customsrcdir", } }“
这是毫无意义的,因为这与执行以下操作相同:
“`Java={ Source = 1.5 }
Java.directories{ 源码="customsrcdir", }“`
我尝试了不同的方法来使所需的DSL起作用。其中一个是使用_ENV设置自定义全局环境,但是后来我意识到在__call之前评估了表格。
我想知道是否有更多lua经验的人使用更高级的表/元表/_ENV技巧实现了此类DSL。
可以使用调用的方式来实现,但解决方案非常复杂,不值得省略 =。如果仍想要表格合并或替换功能,则不太困难。
local function merge(t1, t2)
for k, v in pairs(t2) do
-- 合并表格与表格,除非替换表格是一个数组,
-- 在这种情况下,数组表格会覆盖目标。
if type(t1[k]) == 'table' and type(v) == 'table' and #v == 0 then
merge(t1[k], v)
else
t1[k] = v
end
end
end
local data = {
java = {
source = 1.6,
target = 1.6,
directories = {
sources = "src/main/java",
output = "build/classes",
},
}
}
local dsl = {}
load( [[
java = {
source = 1.5,
directories = {
sources = "customsrcdir",
},
}
]], 'dsl-config', 't', dsl)()
merge(data, dsl)
倾印 data 将导致:
java = {
directories = {
output = "build/classes",
sources = "customsrcdir"
}
source = 1.5,
target = 1.6
}
- 如何将两个不同的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中获取用户配置主目录的跨平台方法
请查看 premake 是如何做的......可能比你现在所做的更优雅的解决方案。 http://en.wikipedia.org/wiki/Premake#Sample_Script