繁体   English   中英

从字符串创建Lua函数

[英]Create Lua function from string

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

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是本地的。

这可以解决吗?

“loadstring不会使用词法作用域进行编译” ,所以不,它不能在loadstring调用之外看到本地人。


这可以解决吗?

那要看。 为什么你首先使用loadtring? Lua支持闭包作为第一类值,所以我从你的例子中看不出为什么你需要 loadtring。

你的例子:

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

如果你有用户可配置的表达式,你想要编译成其他函数,我可以看到一个loadstring的情况,但你的情况与本地c表明并非如此。 你想尝试一些自制的lamda语法吗?

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

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())

如果这样有效,那么印刷什么? 1还是4 它是否从加载函数的位置捕获变量,即使该函数不再存在? 或者它是从它被调用的地方查找的?

第一个意味着函数在任何创建的位置都是词法范围的。 能够在函数退出后访问变量意味着需要动态地将变量提升为upvalue,这不是Lua目前可以做的事情。 就像现在一样,Lua可以在编译期间看到对局部变量的每次访问,因此它知道哪些变量变为upvalues(在性能命中时)以及哪些变量保持为本地变量。

第二个意味着loadstring函数内的变量访问与Lua中的每个其他访问完全不同:Lua使用词法作用域,而不是动态作用域。 这对Lua来说是一个巨大的实现变化,而且是一个非常不一致的变化。

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

如果不需要改变局部变量,那么你可以做的就是将这些值作为参数传递给生成的函数。 您仍然需要手动指定要关闭的变量,但它更好,然后没有。

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

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))

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM