如何 运行 一个字符串并得到一个 table,其中包含代码在 lua 中创建的所有变量?
How to run a string and get a table that has all the variables that the code created in lua?
所以我正在为 LIKO-12 制作自己的 OS,我需要 运行 .lk12 文件,但我需要一个函数来 运行 一个字符串作为代码return 一个 table 包含代码创建的所有变量
示例:
function foo()
return "Hello,"
end
function bar()
return " World!"
end
hello = foo()..bar()
应该 return 具有 2 个功能的 table:
一个名为 foo 的函数 returns "Hello,"
一个名为 bar 的函数 returns “World!”
和一个名为 hello 的变量,其中包含“Hello, World!”
您应该可以使用以下代码从代码中调用函数
vars["foo"]()
或 vars.foo()
谁能帮帮我?
当您创建或使用全局变量时,它实际上存储在称为“环境”的 table 或 _ENV
( 不是 全局, 这是你自动获得的本地)
所以你的代码:
function foo()
return "Hello,"
end
function bar()
return " World!"
end
hello = foo()..bar()
真的在做:
function _ENV.foo()
return "Hello,"
end
function _ENV.bar()
return " World!"
end
_ENV.hello = _ENV.foo().._ENV.bar()
所以如果我们只是将 _ENV
设置为一个新的 table,然后 return 它,那么这正是您想要的 table。您可以使用 load
(这是 运行 字符串的方式)将其作为第四个参数传递。此函数将执行此操作:
function loadAndReturnEnv(codeString)
local env = {}
load(codeString, nil, nil, env)() -- error checking skipped for demonstration
return env
end
但是,请注意所有常见的全局内容,如 string.rep
、table.sort
、load
、print
都不存在于这个新的 _ENV 中。如果那是你想要的,那就太好了。但我想你可能确实想要它们。在那种情况下,我们可以使用 metatable __index
功能,这样如果代码在其 _ENV 中查找某些内容但不存在,它会在我们(调用者的)_ENV 中查找。
function loadAndReturnEnvWithGlobals(codeString)
-- note: env is the environment for the code we're about to run
-- (which will be called _ENV in that code), and _ENV is the environment
-- of the loadAndReturnEnvWithGlobals function (i.e. the "real" environment)
local env = {}
setmetatable(env, {__index=_ENV})
load(codeString, nil, nil, env)() -- error checking skipped for demonstration
setmetatable(env, nil) -- set the table back to normal before we return it
return env
end
但是等等...程序现在可以在您 运行 时调用 print
,但是如果它定义了一个函数,该函数不能调用 print
因为我们删除了在代码 returned 之后 link 回到真实环境。所以我认为解决这个问题的最好方法是离开环境 linked,只复制函数等
function loadAndReturnEnvWithGlobals2(codeString)
local env = {}
setmetatable(env, {__index=_ENV})
load(codeString, nil, nil, env)() -- error checking skipped for demonstration
local result = {}
for k,v in pairs(env) do result[k]=v end
return result
end
尽管这会复制值,所以如果您有任何更改变量的函数,您将看不到更改后的变量。
使用哪个版本由您决定。他们各有利弊。
所以我正在为 LIKO-12 制作自己的 OS,我需要 运行 .lk12 文件,但我需要一个函数来 运行 一个字符串作为代码return 一个 table 包含代码创建的所有变量
示例:
function foo()
return "Hello,"
end
function bar()
return " World!"
end
hello = foo()..bar()
应该 return 具有 2 个功能的 table: 一个名为 foo 的函数 returns "Hello," 一个名为 bar 的函数 returns “World!” 和一个名为 hello 的变量,其中包含“Hello, World!”
您应该可以使用以下代码从代码中调用函数
vars["foo"]()
或 vars.foo()
谁能帮帮我?
当您创建或使用全局变量时,它实际上存储在称为“环境”的 table 或 _ENV
( 不是 全局, 这是你自动获得的本地)
所以你的代码:
function foo()
return "Hello,"
end
function bar()
return " World!"
end
hello = foo()..bar()
真的在做:
function _ENV.foo()
return "Hello,"
end
function _ENV.bar()
return " World!"
end
_ENV.hello = _ENV.foo().._ENV.bar()
所以如果我们只是将 _ENV
设置为一个新的 table,然后 return 它,那么这正是您想要的 table。您可以使用 load
(这是 运行 字符串的方式)将其作为第四个参数传递。此函数将执行此操作:
function loadAndReturnEnv(codeString)
local env = {}
load(codeString, nil, nil, env)() -- error checking skipped for demonstration
return env
end
但是,请注意所有常见的全局内容,如 string.rep
、table.sort
、load
、print
都不存在于这个新的 _ENV 中。如果那是你想要的,那就太好了。但我想你可能确实想要它们。在那种情况下,我们可以使用 metatable __index
功能,这样如果代码在其 _ENV 中查找某些内容但不存在,它会在我们(调用者的)_ENV 中查找。
function loadAndReturnEnvWithGlobals(codeString)
-- note: env is the environment for the code we're about to run
-- (which will be called _ENV in that code), and _ENV is the environment
-- of the loadAndReturnEnvWithGlobals function (i.e. the "real" environment)
local env = {}
setmetatable(env, {__index=_ENV})
load(codeString, nil, nil, env)() -- error checking skipped for demonstration
setmetatable(env, nil) -- set the table back to normal before we return it
return env
end
但是等等...程序现在可以在您 运行 时调用 print
,但是如果它定义了一个函数,该函数不能调用 print
因为我们删除了在代码 returned 之后 link 回到真实环境。所以我认为解决这个问题的最好方法是离开环境 linked,只复制函数等
function loadAndReturnEnvWithGlobals2(codeString)
local env = {}
setmetatable(env, {__index=_ENV})
load(codeString, nil, nil, env)() -- error checking skipped for demonstration
local result = {}
for k,v in pairs(env) do result[k]=v end
return result
end
尽管这会复制值,所以如果您有任何更改变量的函数,您将看不到更改后的变量。
使用哪个版本由您决定。他们各有利弊。