lua tables, simplest way to overload __tostring
Asked Answered
I

1

5

Thanks to all the Lua stackoverflow folks who have discussed how to customized printing tables. After much reading, I post the following and ask the Lua gurus....

  • is this the simplest way?
  • is it too simple (i.e. broken in some way I don't understand)?

Note that the following:

  • allows for private fields (just start their name with "_") that are not to be printed
  • does not add size to the metatable of every object.

My approach rewrites the default tostring method.

_tostring =  _tostring or tostring
function tostring(t)
  if type(t) == "table" then 
    status, stuff = pcall(function() return t:s() end) 
    if status then 
      return stuff 
  end end 
  return _tostring(t) 
end

The above is a little evil (that call to pcall... not my proudest bit of code but, heh, it works).

In any case, now tostring makes the method call t:s() to an object which we can define using the following homebrew object system:

Object={}

function Object:new(o)
   o = o or {} 
   setmetatable(o,self)  
   self.__index = self
   return o
end

Here's the default definition of :s() -- which can be customized in sub-classes.

function Object:s()
  -- can be customized in subclasses
  local out,sep="{",":"
  for x,y in pairs(self) do 
    if string.sub(x,1,1) ~= "_" then
      out = out..sep..x.." "..y 
      sep = " :"
  end end  
  return out .. '}'
end

e.g.

x=Object:new{a=1, _b=2};print(x)
{:a 1}
Indole answered 10/2, 2016 at 23:7 Comment(3)
Why overwrite tostring rather than setting up a __tostring metamethod?Stacee
I'm voting to close this question as off-topic because it shows a working ode, and the OP is asking for Code Review.Coronach
@Coronach working code is not a valid off-topic reason on Stack Overflow. He's asking for an improvement to a specific problem/issue. Which is off-topic on Code Review anywayCuprum
P
13

is this the simplest way?

By far, no. The simplest way would be to add a __tostring function to your metatable.

function MyClass:__tostring()
    return "<MyClass: "..self.foo..">"
end

does not add size to the metatable of every object.

This is not a concern. Only one metatable should exist per class. The memory usage of one entry in a table is negligible.

Overwriting tostring is both ugly and potentially dangerous: what if you (or someone else) is using a library whose objects have an s method that has side effects?

Pattipattie answered 10/2, 2016 at 23:22 Comment(1)
Note that __tostring in Lua 5.1 will not affect calls to lua_tolstring. This was fixed in 5.2 and laterFootgear

© 2022 - 2024 — McMap. All rights reserved.