2009-05-22 118 views
2

假设我有一个文件名为“test.lua”包含以下线路:如何在lua中关闭?

--[[ test.lua --]] 
local f = function() 
    print"local function f in test.lua" 
end 

f_generate = function() 
    local fun = loadstring(" f()") 
-- local env = getfenv(1) 
-- set(fun,env) 
    return fun 
end 
f_generate()() 
--[[ end of test.lua--]] 

因为加载链的全球环境下,尽自己的东西,所以,当我打电话 f_generate()() 我会得到一个错误“试图调用全局'f'(一个零值)”

代码注释表明函数环境不能处理这个问题。

因为表是lua中唯一的数据结构(而且函数环境和其他很多东西都是通过表来实现的),我认为合理的假设闭包也是通过表来实现的,但是我怎样才能得到它?

回答

0

我觉得你混合两种不同的东西:

  1. 关闭:此,f的定义()应该是任何局部变量的要封闭范围内。

    • 将局部变量插入到动态编译的函数中。这没有得到Lua的正式支持。这不是一个环境问题,这是一个范围的事情。

记住:范围的词法,而环境就是每个功能认为“全球空间”。

由文本字符串构造的函数处于不同的词法空间,就好像它处于不同的文件中一样,因此它具有与其他函数分离的自己的作用域。

顺便说一句,'调试'接口让你用函数的局部变量来联系,所以可能有办法。我只是觉得没有必要这样做。

0

您必须删除'本地',否则它将被垃圾收集。

--local f = function() 
f = function() 
    print"local function f in test.lua" 
end 
4

从问题的提出和提供的示例代码中,我看不出有任何需要使用loadstring()当函数和闭包是在语言一流的值。我会考虑做这样的:

 
-- test.lua 
local f = function() 
    print"local function f in test.lua" 
end 

f_generate = function() 
    local fun = function() return f() end 
    return fun 
end 
f_generate()() 
-- end of test.lua 

的动机是清晰的如果有f_generate参数:

​​

通过与loadstring()解析器去明确需要呼叫的范围之外的代码到loadstring()。局部变量不存储在任何环境表中。它们的实现方式与其他语言的实现方式大致相同:存储它们的代码由代码生成器分配,在编译之外不可访问。当然,调试模块(和API)有能力窥视它们,但不建议在调试器之外使用。

保留对在作用域外使用的本地引用的正确方法是作为关闭的真正价值。这就是fun = function() return f() end所实现的目标。在这种情况下,f的值将保留为存储在fun中的函数的最大值。请注意,在实践中,这种包装作为高价是非常有效的。不需要名称查找来查找该值,并且由于我使用了尾部调用,所以也不需要额外的堆栈帧。

+0

本地__cmp__table = { [ “>”] =函数(A,B)返回A> B端, [ “> =”] =函数(A,B)返回> = B端, [ “<”] =函数(a,b)返回一个 gray 2009-05-23 02:55:05

0

请参阅您不能将函数/闭包视为表。考虑下面的代码:

local table = { 
    baz = { 
     blah = "bar" 
    }, 
    foo = table.baz.blah 
} 

在这种情况下,您正在执行相当于从更广泛的范围访问范围更窄的范围内的内容。这对功能来说是不可能的,这意味着如果这是真的,那么你可以访问通常不能正常使用的局部变量。现在

,修复代码:

local __cmp__table = { 
    [">"] = function(a,b) return a>b end, 
    [">="] = function(a,b) return a>=b end, 
    ["<"] = function(a,b) return a<b end, 
    ["<="] = function(a,b) return a<=b end, 
    ["=="] = function(a,b) return a==b end, 
    ["~="] = function(a,b) return a~=b end, 
} 
cmp = function(a, op, b) 
    return __cmp__table[op](a,b) 
end 

这将允许你打电话与适当的比较功能的任何两个变量CMP。如果我错过了关于你的代码的观点,那么请告诉我!