简体   繁体   English

Lua:将上下文传递给loadstring?

[英]Lua: pass context into loadstring?

I'm trying to pass context into a dynamic expression that I evaluate every iteration of a for loop. 我正在尝试将上下文传递给动态表达式,我评估for循环的每次迭代。 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: 我的最终目标(除了掌握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>]]

...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? 这里有没有人能更好地了解我将如何做我正在尝试做的事情?

It's worth noting that setfenv was removed from Lua 5.2 and loadstring is deprecated . 值得注意的是, setfenv已从Lua 5.2中删除,并且不推荐使用loadstring 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: 5.2是相当新的,所以你不必担心它一段时间,但是可以写一个适用于这两个版本的加载例程:

local function load_code(code, environment)
    if setfenv and loadstring then
        local f = assert(loadstring(code))
        setfenv(f,environment)
        return f
    else
        return assert(load(code, nil,"t",environment))
    end
end

local context = {}
context.string = string
context.table = table
-- etc. add libraries/functions that are safe for your application.
-- see: http://lua-users.org/wiki/SandBoxes
local condition = load_code("return " .. args.condition, context)

Version 5.2's load handles both the old loadstring behavior and sets the environment (context, in your example). 5.2版的load处理旧的loadstring行为并设置环境(在您的示例中为context)。 Version 5.2 also changes the concept of environments , so loadstring may be the least of your worries. 版本5.2也改变了环境的概念,因此loadstring可能是您最不担心的。 Still, it's something to consider to possibly save yourself some work down the road. 尽管如此,还是可以考虑为自己节省一些工作。

You can change the context of a function with setfenv() . 您可以使用setfenv()更改函数的上下文。 This allows you to basically sandbox the loaded function into its own private environment. 这允许您基本上将加载的函数沙盒化到其自己的私有环境中。 Something like the following should work: 像下面这样的东西应该工作:

local context = {}
local condition = assert(loadstring('return ' .. args.condition))
setfenv(condition, context)
for _, it in ipairs(model) do
    context['each'] = it
    if condition() then
        -- ...

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 want condition to be able to access (eg if you want it to have access to the math package then you'll need to stick that into context ). 但是,请注意,您需要将任何顶级绑定公开到您希望condition能够访问的context表中(例如,如果您希望它能够访问math包,那么您需要坚持使用进入context )。 Alternatively, if you don't have any problem with condition having global access and you simply want to deal with not making your local a global, you can use a metatable on context to have it pass unknown indexes through to _G : 或者,如果您对具有全局访问权限的condition没有任何问题,并且您只想处理不使本地变为全局,则可以在context使用metatable将其传递给_G

setmetatable(context, { __index = _G })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将上下文从 *ngIf 传递给 Angular 5 模板 - How to pass context to Angular 5 template from *ngIf Django将上下文从不同的应用程序传递到一个模板 - Django pass context from different apps to one template 如何将上下文对象作为Django URL模板标记参数传递 - How to pass context objects as Django url template tag arguments 如何将选定的命名参数传递给 Jinja2 的包含上下文? - How to pass selected, named arguments to Jinja2's include context? 第一次通过 for 循环后,django 模板中的上下文变量不可用 - Context variables not available in django template after first pass through a for loop Django 如何将自定义变量传递给上下文以在自定义管理模板中使用? - Django how to pass custom variables to context to use in custom admin template? 如何将我的上下文变量传递给 Django 中的 javascript 文件? - How can I pass my context variables to a javascript file in Django? 如何在不在所有视图中实际指定上下文的情况下将上下文传递给模板? - How do I pass context to a template without actually specifying it in all views? 如何正确地将多个参数(从模板/上下文)传递到Django中的视图? - How do I correctly pass multiple arguments (from the template/context) to a view in Django? Lua模板处理器问题 - Lua template processor question
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM