How to prevent ..., function asText improved

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

How to prevent ..., function asText improved

Jon Kleiser-2
I wrote you in December about a function asText(...) that I had just made,
and asked about the problem I had with handling circular references. David
Jeske replied and suggested that I should keep track of table references.
As my need to solve this just got more pressing, I made the following
improved version, along David's suggestion:


function asText(obj)
   -- Returns a textual representation of "any" Lua object,
   -- incl. tables (and nested tables).
   -- Functions are not decompiled (of course).
   -- Try: print(asText({{"a", "b"}; c=3}))

   visitRef = {}
   visitRef.n = 0

   asTxRecur = function(obj, asIndex)
      if type(obj) == "table" then
         if visitRef[obj] then
            return "@"..visitRef[obj]
         end
         visitRef.n = visitRef.n +1
         visitRef[obj] = visitRef.n

         local begBrac, endBrac
         if asIndex then
            begBrac, endBrac = "[{", "}]"
         else
            begBrac, endBrac = "{", "}"
         end
         local t = begBrac
         local k, v = nil, nil
         repeat
            k, v = next(obj, k)
            if k ~= nil then
               if t > begBrac then
                  t = t..", "
               end
               t = t..asTxRecur(k, 1).."="..asTxRecur(v)
            end
         until k == nil
         return t..endBrac
      else
         if asIndex then
            -- we're on the left side of an "="
            if type(obj) == "string" then
               return obj
            else
               return "["..obj.."]"
            end
         else
            -- we're on the right side of an "="
            if type(obj) == "string" then
               return '"'..obj..'"'
            else
               return tostring(obj)
            end
         end
      end
   end -- asTxRecur

   return asTxRecur(obj)
end -- asText


I find this function very useful when I need to inspect complex table
structures to see if they contain what I intended them to do. When there
are several nested levels, however, the output may take some time to make
sense of.

I love Lua more and more; it's a great little language!

/Jon


Reply | Threaded
Open this post in threaded view
|

Re: How to prevent ..., function asText improved

Tomas Guisasola Gorham-2
	Jon,

	your solution doesn't work when a function is the index of a table
neither when a string with a space (for instance) in it is the index.
	You can solve this by eliminating the 'asIndex' parameter and
forcing the characters '[' and ']' at the left side of the assignment.
I also take the liberty to change your repeat-until loop to a while-do-end
to eliminate a redundant test inside (if k ~= nil ...).

function asText(obj)
   visitRef = {}
   visitRef.n = 0

   asTxRecur = function(obj)
      if type(obj) == "table" then
         if visitRef[obj] then
            return "@"..visitRef[obj]
         end
         visitRef.n = visitRef.n +1
         visitRef[obj] = visitRef.n

         local begBrac, endBrac = "{", "}"
         local t = begBrac
         local k, v = next(obj, nil)
         while k do
            if t > begBrac then
               t = t..", "
            end
            t = t.."["..asTxRecur(k).."]="..asTxRecur(v)
            k, v = next(obj, k)
         end
         return t..endBrac
      else
         if type(obj) == "string" then
            return '"'..obj..'"'
         else
            return tostring(obj)
         end
      end
   end -- asTxRecur

   return asTxRecur(obj)
end -- asText

	Also, you couldn't distinguish two different tables with the same
contents.  As you are numbering each table you write, you can change 'begBrac'
to "{@"..visitRef.n and you will be printing each table with a number.
After that you can write every reference to each table (despite it is a
circular reference) with its number and the mentioned difference will be
shown.
	I made a function like that (about a year or two), but as my
problem doesn't have circular references I have never tried to resolve it.
On the other side, I made some effort to indent tables.  If you are interested
in it, I'm merging both functions and can send you a copy.

	Tomas