第一版是为 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。保留所有权利。 |