登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

秒大刀 博客

好好学习 天天向上

 
 
 

日志

 
 
 
 

lua readonly table  

2009-04-02 11:11:38|  分类: Lua |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

    lua中metatable的功能还是很强大的,本例展示一个lua的readonly table(参考《Lua程序设计(第二版)》中文版 13.4.5 只读的table)

-- 修改只读表格的错误处理函数
 function error_readonly_handler(t, k, v)
     error("attempt to update a read-only table", 2)
 end
  -- 将表格t的顶层包装为只读表格(非递归只读)
 function readonly_table(t)
     local proxy = {}
     setmetatable(proxy, {__index = t, __newindex = error_readonly_handler});
     return proxy;
 end
  -- 向给定的表格中插入一跳只读的记录并进行必要的key合法性检测
 function table_add_readonly_row(t, r, key)
     local row = readonly_table(r)
     if row == nil then error("row can not be nil", 2) end
     if key == nil then
         t[#t + 1] = row
     else
         if row[key] == nil then error("row[key] can not be nil") end
         if t[row[key]] ~= nil then error("t[row[key]] already exists") end
         t[row[key]] = row
     end
 end
  -- 将数据包装为只读表格的示例
 function LoadTable_Data()
     local proxy = {}
     local index = "ID"
     table_add_readonly_row(proxy, {["ID"] = 10010, ["Name"] = "Lucy"}, index)
     -- ...
     table_add_readonly_row(proxy, {["ID"] = 10011, ["Name"] = "Jack"}, index)
     return readonly_table(proxy)
 end  

    注意下面的写法是没有用的,可以正常执行,但t仍然是可以修改的。因为__index只有当表格中找不到元素时才会触发,所以必须通过一个空的代理表格进行中转包装。

setmetatable(t, {__index = t, __newindex = error_readonly_handler}) 


2011-12-28
    lua中的长度操作符'#'可以方便的求的表或数组的大小,但对于稀疏表和采用了索引代理表的表‘#’的计算结果却是错误的。以下方法采用next函数进行对表进行遍历计数,时间复杂度为O(n),但能得到表格的真实大小,这在某些应用下甚为有用。
--- @brief 得到表大小,对稀疏表、索引元表为表的表也适用
function table_size(t)
if t == nil then return 0 end
-- 计算稀疏表的大小
local n = 0
local index = next(t)
while index ~= nil do
n = n + 1
index = next(t, index)
end
-- 计算代理索引表的大小
local meta = getmetatable(t)
if meta ~= nil then
local h = meta.__index
if type(h) == "table" then
n = n + table_size(h)
end
end
return n
end
    lua 5.2中支持table的__len metatable重写,可将以上函数设入长度操作符元表,这样就可通过‘#’很自然的得到表的真实长度了。
  评论这张
 
阅读(2033)| 评论(3)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018