mat*_*uty 3 environment evaluation lua environment-variables
这个问题有一些参考问题Evaluating expression in Lua in Mathematics Environment 下面的代码有效。
tbl = {}
tbl.sin = math.sin
tbl.cos = math.cos
function mathEval(exp)
return load("return " .. exp, exp, "t", tbl)()
end
print(mathEval("sin(0)"))
print(mathEval("sin(0)+cos(1)+2^2"))
Run Code Online (Sandbox Code Playgroud)
但是,下面的代码不起作用。
tbl = {}
tbl.sin = math.sin
tbl.cos = math.cos
function mathEval(exp)
return load("return " .. tostring(exp), tostring(exp), "t", tbl)()
end
print(mathEval(sin(0)))
print(mathEval(sin(0)+cos(1)+2^2))
Run Code Online (Sandbox Code Playgroud)
我想在不使用引号的情况下计算表达式。那怎么办呢?
该行的问题print(mathEval(sin(0)+cos(1)+2^2))在于, 的参数在运行之前mathEval进行评估,因此评估变量并且不能推迟到;的环境中。也就是说,获取一个值,并且根本不需要计算表达式! mathEvalsincosmathEvalmathEval
首先,在不使用的情况下评估此类数学表达式的一种选择mathEval是简单地暂时改变您的环境:
local prev_env = _ENV -- this is needed to restore the environment later on
_ENV = tbl -- enter custom environment
local result = sin(0)+cos(1)+2^2
_ENV = prev_env -- restore environment
print(result)
Run Code Online (Sandbox Code Playgroud)
如果你想mathEval作为一个方便的助手,你必须将表达式作为函数传递,将值返回给表达式,这样调用函数就会计算表达式;这允许您推迟初始化。您必须使用一个名为 的强大函数setfenv,它允许您更改 ; 的环境func。不幸的是,这个_ENV在 Lua 5.2 及更高版本中被删除了。那么代码就变得很简单:
local function mathEval(func)
setfenv(func, tbl)
return func
end
mathEval(function() return sin(0)+cos(1)+2^2 end)
Run Code Online (Sandbox Code Playgroud)
setfenv可以使用该debug库在 Lua 5.2 中复制,因为 Lua 内部实现_ENV为上值,如Leafo 所示:
local function setfenv(fn, env)
local i = 1
while true do
local name = debug.getupvalue(fn, i)
if name == "_ENV" then
debug.upvaluejoin(fn, i, (function()
return env
end), 1)
break
elseif not name then
break
end
i = i + 1
end
return fn
end
Run Code Online (Sandbox Code Playgroud)