[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: using a closure for enumerating table
- From: Andrew Starks <andrew.starks@...>
- Date: Wed, 20 Jun 2012 02:55:43 -0500
Best Regards,
Andrew Starks
Tightrope Media Systems
Co-Founder
800 Transfer Road, Suite 1B, Saint Paul MN 55114
(651) 603-4201
Carousel Digital Signage by Tightrope Media Systems has been voted the #1 in
digital signage by readers of Prov AV Magazine.
On Mon, Jun 18, 2012 at 10:34 AM, jseb <gmane2010@finiderire.com> wrote:
>
>
> I guess i must practice more before getting fluent in Lua !
So...I'm sure I'll be thrown off the list for being obsessive, but I
was thinking about how to generalize this and then I couldn't stop.
Now it works with keys and values as tables, traps cycles and uses a
table as the invariant for the iterator, which is a closure:
---BEGIN
local ts = tostring
function deep_pairs(t)
local invar = setmetatable({
visited = {},
path = {t},
keys = {},
values = {},
}, {
__index = function(invar, index)
return (index == "key" or index == "value") and
invar[index.."s"][#invar[index.."s"]] or nil
end
})
local _visited = setmetatable({},{
__index = function(t, index)
local had = invar.visited[index]
invar.visited[index] = had and had + 1 or 1
return had and invar.visited[index]
end
})
local _ = _visited[t] or nil
local function dp()
invar.keys[#invar.path], invar.values[#invar.path] =
next(invar.path[#invar.path], invar.keys[#invar.path])
local key, value = invar.keys[#invar.path], invar.values[#invar.path]
if type(key) == "nil" then
--check for situation where you have [table] = table and
--the key is done processing and the value hasn't yet been
--processed and it hasn't been cycled before.
if invar.keys[#invar.keys] == invar.path[#invar.path] and
type(invar.values[#invar.values]) == "table" and
not _visited[invar.values[#invar.values]] then
invar.path[#invar.path] = invar.values[#invar.values]
else
invar.path[#invar.path] = nil
end
return #invar.path > 0 and dp() or nil
else
for x=1,2 do
local e = x % 2 == 1 and {key, "key"} or {value, "value"}
if type(e[1]) == "table" and _visited[e[1]] then
invar[e[2] .. "_cycled"] = e[1]
elseif type(e[1]) == "table" then
invar.path[#invar.path + 1] = e[1]
--return now so that you don't
touch a value table
--that still needs to be processed.
return invar
end
end
return invar
end
end
return dp, t
end
---[[simple test
my_table = {[1] = "some stuff", [{"A value in a table key"}] = "some
thing as value ",nested_key = {barfly = true, barferson = true} ,[2] =
"more stuff",[{"bluch"}] = {"blee"}, [0] = "yeah, right." }
my_table[5] = my_table.nested_key
for b in deep_pairs(my_table) do
print(ts(b.path[#b.path])..":","["
..ts(b.key).."]","-->",b.value,"depth:",#b.path,"cycled:",ts(b.key_cycled)
.."/"..ts(b.value_cycled))
end
--]]
--END