lua-users home
lua-l archive

Re: Self-initializing tables

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


2016年02月23日 7:26 GMT+02:00 Paul K <paul@zerobrane.com>:
> Dirk,
>
>> A module is attached that contains the following comments:
>
> Missing attachment?
>
> Paul.
>
-- selfinit.lua © Dirk Laurie 2016 MIT license
-- Published as a contribution to lua-l@lists.lua.org on 2015年02月23日
-- Self-initializing table. The point is that `tbl[key]` is never nil.
-- tbl = selfinit(tbl) -- makes an existing table self-initializing
-- and returns it
-- tblx = tbl.x -- tbl.x is an empty table with the same
-- metatable as x
-- tbl.a.b.c.d = 'item' -- tbl.a, tbl.a.b, tblc.a.b.c are created too,
-- even if `item` is nil.
-- tbl = selfinit() -- creates a new self-initializing table
-- WARNING: The implications are strongly counterintuitive. 
-- 1. You will need `rawget` to find out whether a table entry exists.
-- 2. If `ipairs` is found by the module loader to treat an empty self-
-- initializing table as non-empty, it is monkey-patched to use `rawget`.
-- The module is not paranoid about abuse. The only legitimate error
-- is to try to overwrite an existing __index metamethod. If you supply
-- a 'tbl' on which 'setmetatable' fails, that's the error you will get.
local selfinit, selfinit_mt, selfinit_index 
selfinit_index = function(tbl,item)
 local sit = setmetatable({},getmetatable(tbl)) 
 rawset(tbl,item,sit)
 return sit
end
selfinit_mt = {__index = selfinit_index}
--- selfinit(tbl) makes 'tbl' self-initializing and returns it.
-- selfinit() is equivalent to selfinit{}
selfinit = function(tbl)
 local mt
 mt = getmetatable(tbl)
 if mt then
 if mt.__index then 
 error("Table already has an index metamethod",2)
 end
 mt.__index = selfinit_index
 return tbl
 end
 return setmetatable(tbl or {},selfinit_mt)
end
local old_ipairs = ipairs
local selfinit_inext = function(tbl,key)
 if not key then 
 local val = rawget(tbl,1)
 if val then return 1, val
 else return
 end
 end
 key=key+1
 return rawget(tbl,key),key
end
 
-- monkey-patch ipairs
for k in ipairs(selfinit{}) do
 debug.getregistry().ipairs_before_selfinit = ipairs
 ipairs = function(tbl) return selfinit_inext, tbl end
 break
end
 
return selfinit

AltStyle によって変換されたページ (->オリジナル) /