我有这个代码:
function createRect(x, y, w, h) local rect = { type = "rect", x = x, y = y, w = w, h = h, translate = function(rect, vector) assert(vector.type == "vector2d") local rect = shapes.createRect(rect.x + vector.x, rect.y + vector.y, rect.w, rect.h) end, } return rect end translate = function(rect, vector) assert(vector.type == "vector2d") local rect = shapes.createRect(rect.x + vector.x, rect.y + vector.y, rect.w, rect.h) end local o = createRect(2,3,4,5) local q = createRect(2,3,4,5) print(o.translate, q.translate, translate)
这是一些非常简单的代码,用于测试Lua中的测试工厂函数,非常让人联想到JS模块模式.在谈论工厂功能时,人们通常会抱怨的是内存占用.因为o
并且q
刚刚被分配translate()
,我认为当然它们具有不同的功能.但是我被证明是错的:
function: 0x7fcdbe600d50 function: 0x7fcdbe600d50 function: 0x7fcdbe600d90
为什么是这样?怎么会这样呢?我假设是o.translate
和q.translate
不同的功能,但它们是相同的......
怎么会这样呢?我假设是
o.translate
和q.translate
不同的功能,但它们是相同的......
通常你是正确的,但Lua 5.2引入了一个优化,如果满足某些条件,可以缓存匿名函数.具体来说,如果它引用的值在构造之间没有变化,那么该匿名函数的第一个创建的实例将被重用.
在repl.it中运行您的示例Lua 5.1,将其显示为一个可能的输出:
function: 0xb81f30 function: 0xb81f00 function: 0xb82ca0
但是在melpon.org/wandbox 下运行它,Lua 5.2+,显示:
function: 0x14f0650 function: 0x14f0650 function: 0x14efb40
在您的示例中,为每个调用createRect
创建并返回一个不同的rect
表,但rect.translate
由于此优化,该字段被分配了与lua值相同的匿名函数.
另见
http://lua-users.org/lists/lua-l/2010-07/threads.html#00339
http://lua-users.org/lists/lua-l/2010-07/msg00862.html
http://lua-users.org/lists/lua-l/2010-05/threads.html#00617