# Help me solve this lua puzzle...printing table contents recursively

I’m trying to make it so that I can print out a table in a way where the output is valid lua code for initializing a table with the same contents. ie:

for

``````foo = {
{ 6, 1, true },
{ 4, 2, { 5, 1, { 4, 3, "all" } } },
{ 3, 3, "all" },
{ 6, 4, "every2" },
{ 4, 5, "every3" },
{ 2, 6, "every4" },
{ 8, 7, "random" },
{ 9, 8, "long" }
}
``````

running

``````tprint(foo, "foo")
``````

prints (tabbing/whitespace doesn’t need to be exactly the same)

``````foo = {
{ 6, 1, true },
{ 4, 2,
{ 5, 1,
{ 4, 3, "all" }
}
},
{ 3, 3, "all" },
{ 6, 4, "every2" },
{ 4, 5, "every3" },
{ 2, 6, "every4" },
{ 8, 7, "random" },
{ 9, 8, "long" }
}
``````

I have a recursive solution figured out for printing out the values based on indexing, but that only works if the table has been initialized with the same number of contents. Spent more time than I’m willing to admit trying to figure this out, but it’s stumped me. Anyone have the desire to solve this programming puzzle?

My current solution:

``````foo = {
{ 6, 1, true },
{ 4, 2, { 5, 1, { 4, 3, "all" } } },
{ 3, 3, "all" },
{ 6, 4, "every2" },
{ 4, 5, "every3" },
{ 2, 6, "every4" },
{ 8, 7, "random" },
{ 9, 8, "long" }
}

tprint = function(t, n, _k)
n = n ~= nil and n or 'n'
if type(t) == 'table' then
for k,v in pairs(t) do
if _k ~= nil then
k = '\t' .. _k .. '[' .. k .. ']'
if type(v) == 'table' then
-- print(k .. ' is a table')
end
else
k = n .. '[' .. k .. ']'
-- print(k .. ' is a table')
end
tprint(v, n, k)
end
else
t = type(t) == 'string' and '"' .. t .. '"' or t
print(_k .. ' = ' .. tostring(t))
end
end

tprint(foo, "foo")

-- outputs
foo[1][1] = 6
foo[1][2] = 1
foo[1][3] = true
foo[2][1] = 4
foo[2][2] = 2
foo[2][3][1] = 5
foo[2][3][2] = 1
foo[2][3][3][1] = 4
foo[2][3][3][2] = 3
foo[2][3][3][3] = "all"
foo[3][1] = 3
foo[3][2] = 3
foo[3][3] = "all"
foo[4][1] = 6
foo[4][2] = 4
foo[4][3] = "every2"
foo[5][1] = 4
foo[5][2] = 5
foo[5][3] = "every3"
foo[6][1] = 2
foo[6][2] = 6
foo[6][3] = "every4"
foo[7][1] = 8
foo[7][2] = 7
foo[7][3] = "random"
foo[8][1] = 9
foo[8][2] = 8
foo[8][3] = "long"
``````
1 Like

also, this would be a welcome addition to the core library

1 Like

happy to submit a PR (or whoever solves this can submit one)! I started with what was here: https://github.com/monome/norns/blob/fd2485af8228ab11d111d1283c9b314857fe5d32/lua/lib/tabutil.lua#L9

If this is desired for crow (I know I’d get a lot of use out of it, but this might be less useful for others and not worth the space it takes up to always load), I’d be happy to optimize it down as small as possible to put somewhere in here: https://github.com/monome/crow/tree/master/util

1 Like

just a disclaimer - I don’t really know lua, but I’m a sucker for a programming puzzle

looking at the problem, it struck me as similar to json encoding/serialization, so I took a quick look online for a lua json library
using this https://github.com/rxi/json.lua/blob/master/json.lua library’s encode function, it was pretty straightforward to get something working - you might be able to trim it down for the specific use case too

2 Likes

ah cool, good find, I’ll see if I can tweak and make their thing work.

I also like programming puzzles, but I had to accept defeat and move on from this one

1 Like

There are a few edge cases depending on what is in the input table. See this for inspiration:

http://lua-users.org/wiki/TableSerialization

2 Likes

I think this should work for the test data given. It most definitely does not preserve whitespace though that shouldn’t be too much trouble to sort out. It also will not re-escape strings when printing so `"This \"is\" a string"` will be printed as `"This "is" a string"` which could definitely cause some issues. I don’t think it would be too tricky to add something to this to iterate over the string and add the `\` characters as needed.
This function also adds trailing commas but everything should still work correctly if the goal is to print working lua code.

Function:

``````tprint = function(table, name)
local str = name .. '='

step = function(item)
if type(item) == 'table' then
str = str .. '{'
for i = 1, #item do
step(item[i])
end
str = str .. '},'
elseif type(item) == 'string' then
str = str .. '"' .. item .. '",'
else
str = str .. tostring(item) .. ','
end
end

step(table)

-- strip out the final trailing ',' if there is one
if (str:sub(#str)) == ',' then
print(str:sub(1, #str - 1))
else
print(str)
end
end

``````

Input:

``````foo = {
{ 6, 1, true },
{ 4, 2, { 5, 1, { 4, 3, "all" } } },
{ 3, 3, "all" },
{ 6, 4, "every2" },
{ 4, 5, "every3" },
{ 2, 6, "every4" },
{ 8, 7, "random" },
{ 9, 8, "long" }
}
``````

output:

``````foo={{6,1,true,},{4,2,{5,1,{4,3,"all",},},},{3,3,"all",},{6,4,"every2",},{4,5,"every3",},{2,6,"every4",},{8,7,"random",},{9,8,"long",},}
``````
1 Like

For general debugging I’ve been using `inspect` - it’s on luarocks, and this is the source: https://github.com/kikito/inspect.lua. It seems to put out valid Lua as far as I’ve noticed - that’s not been a requirement for me.

1 Like

On the other hand, from the `README`:

This method is not appropriate for saving/restoring tables. It is meant to be used by the programmer mainly while debugging a program.

Make of that what you will…

1 Like

How do you use luarocks stuff w crow/norns?

Not sure you can - but you could presumably just do the install on a laptop and then drop the files into `lib` with some path edits. That’s a hack though - full Luarocks support would be nice.

1 Like

gotcha was just making sure there wasn’t some thing i was missing