第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但有一些差异。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目。
![]() |
Lua 编程 | ![]() |
| 第二部分。表和对象 第 17 章。弱表 |
一种常见的编程技术是用空间换取时间。您可以通过备忘函数的结果来加速某些函数,以便以后使用相同参数调用函数时,它可以重复使用结果。
想象一下一个通用服务器,它接收包含 Lua 代码的字符串的请求。每次收到请求时,它都会对字符串运行 loadstring,然后调用结果函数。但是,loadstring 是一个昂贵的函数,并且对服务器的某些命令可能非常频繁。服务器可以备忘 loadstring 的结果,使用辅助表,而不是在每次接收到诸如 "closeconnection()" 的通用命令时都反复调用 loadstring。在调用 loadstring 之前,服务器会在表中检查该字符串是否已翻译。如果找不到字符串,则(且仅当)服务器调用 loadstring 并将结果存储到表中。我们可以将此行为打包到一个新函数中
local results = {}
function mem_loadstring (s)
if results[s] then -- result available?
return results[s] -- reuse it
else
local res = loadstring(s) -- compute new result
results[s] = res -- save for later reuse
return res
end
end
此方案节省的开销可能很大。但是,它也可能造成意想不到的浪费。虽然一些命令会反复执行,但许多其他命令只执行一次。结果表 results 会逐渐累积服务器接收过的所有命令及其各自的代码;一段时间后,这会耗尽服务器的内存。弱表为这个问题提供了一个简单的解决方案。如果 results 表具有弱值,则每个垃圾回收周期都会删除所有在该时刻未使用的翻译(这意味着几乎所有翻译)。
local results = {}
setmetatable(results, {__mode = "v"}) -- make values weak
function mem_loadstring (s)
... -- as before
实际上,由于索引始终是字符串,如果需要,我们可以使该表完全弱。
setmetatable(results, {__mode = "kv"})
最终结果完全相同。
备忘技术还可用于确保某种对象的唯一性。例如,假设一个系统将颜色表示为表,其中字段 red、green 和 blue 处于某个范围内。一个天真的颜色工厂为每个新请求生成一个新颜色
function createRGB (r, g, b)
return {red = r, green = g, blue = b}
end
使用记忆技术,我们可以对相同的颜色重复使用相同的表。要为每种颜色创建一个唯一键,我们只需将颜色索引与中间的分隔符连接起来
local results = {}
setmetatable(results, {__mode = "v"}) -- make values weak
function createRGB (r, g, b)
local key = r .. "-" .. g .. "-" .. b
if results[key] then return results[key]
else
local newcolor = {red = r, green = g, blue = b}
results[key] = newcolor
return newcolor
end
end
这种实现的一个有趣后果是用户可以使用原始相等运算符比较颜色,因为两个共存的相等颜色始终由同一张表表示。请注意,同一颜色可能在不同时间由不同的表表示,因为垃圾回收周期会时不时地清除 results 表。但是,只要给定颜色正在使用,它就不会从 results 中删除。因此,只要一种颜色存活足够长的时间与一种新颜色进行比较,它的表示形式也存活足够长的时间以供新颜色重复使用。
| 版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 | ![]() |