2012-07-08 83 views
3

我从Lua中的字符串创建函数(x)。我正在使用的代码是从字符串创建Lua函数

function fcreate(fs) 
return assert(loadstring("return function (x) return " .. fs.." end"))() 
end 

这适用于全局变量,

u=fcreate("math.sin(x)") 

做对了。

但是,它似乎并不喜欢局部变量。所以

local c=1 
u=fcreate("math.sin(x)+c") 

不会工作,因为c是本地的。

这是可以修复的吗?

+0

为什么downvote? – 2013-06-03 01:15:33

回答

13

"loadstring does not compile with lexical scoping",所以不,看不到当地人拨打loadstring以外的地方。


这是可以解决的?

这取决于。为什么你首先使用loadtring? Lua支持闭包作为第一类值,所以我不能从你的例子中看到为什么需要 loadstring。

你举的例子:

u = fcreate("math.sin(x)+c") 

,而不需要被重写为loadstring或您的fcreate功能:

u = function(x) return math.sin(x)+c end 

这当然是一样的:

function u(x) return math.sin(x) + c end 

我如果您拥有user-con,可以查看loadstring的情况你想编译成一些其他功能的可模拟表达式,但你的案例与当地的c暗示情况并非如此。你是否想尝试一些家庭式的lamda语法?

+8

我解决你的问题* *在第一线,连接你为什么你的代码不能工作,你希望它的方式Lua的作者自己的解释。然后,因为我很好,想要有所帮助,我也试图解决你的问题*(注意分隔两部分的水平法则)。这后一部分主要是由猜测的,因为你的问题的情况下/要求没有说明,所以我贴一些额外的信息,并要求澄清您的要求,因此有可能进一步提供帮助。谢谢你的奖励。 – Mud 2012-07-08 17:59:23

2

不能以任何合理的方式完成。对于为什么一个例子,看看这个:

function makefunction(name) 
    local a = 1 
    local b = 2 
    local c = 3 
    -- ... 
    return assert(loadstring("return " .. name)) 
end 

local a = 4 
local func = makefunction("a") 
print(func()) 

如果这个工作,什么是印刷? 14?它是否从函数加载的地方捕获变量,即使该函数不再存在?还是从它被称为的地方查找它?

第一个意思是该函数在词汇的任何地方被创建。在函数退出后能够访问变量意味着该变量需要动态地升级为upvalue,这不是Lua现在可以做的事情。现在,Lua可以在编译过程中看到每个对局部变量的访问权限,因此它知道哪些变量将变为upvalues(在性能命中时)以及哪些变量保持为当地变量。

第二个意思是说,在d函数内的变量访问将与Lua中的所有其他访问完全不同:Lua使用词汇范围而不是动态范围。这在Lua中会有一个巨大的实施变化,而且是非常不一致的。

所以,无论是支持的。你可以控制一个动态加载函数的环境,使用Lua 5.1中的setfenv或Lua 5.2中的load(...)参数env,但这些都不允许你自动访问局部变量。

1

的东西,如果你不需要变异的局部变量,你可以做的是通过这些值作为参数传递给生成的函数。你仍然需要手动指定要关闭的变量,但它更好,然后什么也不做。

例如,你可以建立你的闭合看起来像

return (function(a,b,c) 
    return function(x) return print(a, x) end 
end)(...) 

我们可以做的是通过改变你的函数看起来像

function fcreate(variables, fs) 

    local varnames = {} 
    local varvalues = {} 
    local nvars = 0 
    for n,v in pairs(variables) do 
    nvars = nvars + 1 
    table.insert(varnames, n) 
    table.insert(varvalues, v) 
    end 

    local chunk_str = (
    'return (function(' .. table.concat(varnames, ',') .. ') ' .. 
     'return function(x) return ' .. fs .. ' end ' .. 
     'end)(...)' 
) 

    return assert(loadstring(chunk_str))(unpack(varvalues, 1, nvars)) 

end 

local a = 1; 
local f = fcreate({a=a}, 'x+a') 
print(f(1), f(2))