Lua:将上下文传递到加载字符串中?
我试图将上下文传递到一个动态表达式中,我会评估 for 循环的每次迭代。我知道加载字符串仅在全局上下文中计算,这意味着局部变量不可访问。就我而言,为了字符串评估的目的,我通过将本地转换为全局来解决此限制。这就是我所拥有的:
require 'cosmo'
model = { { player = "Cliff", age = 35, gender = "male" }, { player = "Ally", age = 36, gender = "female" }, { player = "Jasmine", age = 13, gender = "female" }, { player = "Lauren", age = 6.5, gender = "female" } }
values = { eval = function(args)
output = ''
condition = assert(loadstring('return ' .. args.condition))
for _, it in ipairs(model) do
each = it
if condition() then
output = output .. each.player .. ' age: ' .. each.age .. ' ' .. '\n'
end
end
return output
end }
template = "$eval{ condition = 'each.age < 30' }"
result = cosmo.fill(template, values)
print (result)
我的最终目标(除了掌握 Lua 之外)是构建一个类似 XSLT 的诱人引擎,我可以在其中执行以下操作:
apply_templates{ match = each.age > 30}[[<parent-player>$each.player</parent-player>]]
apply_templates{ match = each.age > 30}[[<child-player>$each.player</child-player>]]
...并生成不同的输出。目前,我仍坚持上述通过全球分享本地背景的鹰派方式。这里有人对我如何去做我想做的事情有更好的见解吗?
I'm trying to pass context into a dynamic expression that I evaluate every iteration of a for loop. I understand that the load string only evaluates within a global context meaning local variables are inaccessible. In my case I work around this limitation by converting a local into a global for the purpose of the string evaluation. Here's what I have:
require 'cosmo'
model = { { player = "Cliff", age = 35, gender = "male" }, { player = "Ally", age = 36, gender = "female" }, { player = "Jasmine", age = 13, gender = "female" }, { player = "Lauren", age = 6.5, gender = "female" } }
values = { eval = function(args)
output = ''
condition = assert(loadstring('return ' .. args.condition))
for _, it in ipairs(model) do
each = it
if condition() then
output = output .. each.player .. ' age: ' .. each.age .. ' ' .. '\n'
end
end
return output
end }
template = "$eval{ condition = 'each.age < 30' }"
result = cosmo.fill(template, values)
print (result)
My ultimate goal (other than mastering Lua) is to build out an XSLT like tempting engine where I could do something like:
apply_templates{ match = each.age > 30}[[<parent-player>$each.player</parent-player>]]
apply_templates{ match = each.age > 30}[[<child-player>$each.player</child-player>]]
...And generate different outputs. Currently I'm stuck on my above hawkish means of sharing a local context thru a global. Does anyone here have better insight on how I'd go about doing what I'm attempting to do?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
值得注意的是
setfenv
已从 Lua 5.2 中删除,并且 < code>loadstring 已弃用。 5.2 是相当新的,所以你暂时不必担心它,但可以编写一个适用于两个版本的加载例程:版本 5.2 的
load
处理旧的loadstring
行为并设置环境(上下文,在你的例子中)。 5.2 版本还改变了环境的概念,因此loadstring< /code> 可能是您最不用担心的。尽管如此,还是值得考虑一下,这样可能会为自己节省一些工作。
It's worth noting that
setfenv
was removed from Lua 5.2 andloadstring
is deprecated. 5.2 is pretty new so you won't have to worry about it for a while, but it is possible to write a load routine that works for both versions:Version 5.2's
load
handles both the oldloadstring
behavior and sets the environment (context, in your example). Version 5.2 also changes the concept of environments, soloadstring
may be the least of your worries. Still, it's something to consider to possibly save yourself some work down the road.您可以使用
setfenv()
。这基本上允许您将加载的函数沙箱到它自己的私有环境中。像下面这样的东西应该可以工作:
这也将防止条件值能够访问您不希望它访问的任何数据,或者更重要的是,修改您不希望它访问的任何数据。但请注意,您需要将任何顶级绑定公开到您希望
condition
能够访问的context
表中(例如,如果您希望它有权访问math
包,那么您需要将其粘贴到context
中)。或者,如果您对具有全局访问权限的condition
没有任何问题,并且您只是想处理不使本地成为全局的问题,则可以在context
上使用元表让它将未知索引传递给_G
:You can change the context of a function with
setfenv()
. This allows you to basically sandbox the loaded function into its own private environment. Something like the following should work:This will also prevent the condition value from being able to access any data you don't want it to, or more crucially, modifying any data you don't want it to. Note, however, that you'll need to expose any top-level bindings into the
context
table that you wantcondition
to be able to access (e.g. if you want it to have access to themath
package then you'll need to stick that intocontext
). Alternatively, if you don't have any problem withcondition
having global access and you simply want to deal with not making your local a global, you can use a metatable oncontext
to have it pass unknown indexes through to_G
: