lua-users home
lua-l archive

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

Best Regards,

Andrew Starks
Tightrope Media Systems

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 <> 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:

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
	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]
	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]
				invar.path[#invar.path] = nil
			return  #invar.path > 0 and dp() or nil
			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
			return invar
	return dp, t

---[[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