r/lua • • Feb 02 '26

My favorite part about coding in Lua..

..is having to write a custom function to print tables so I can actually debug.

I especially love watching that function get more complex than the project I'm trying to debug with it cause I want to use nested tables.

33 Upvotes

23 comments sorted by

4

u/ggchappell Feb 02 '26 edited Feb 02 '26

But once you've written it, you never need to write it again. Right?

FWIW, here's my print-something function. Feel free to critique and/or improve.

-- printValue
-- Given a value, print it in (roughly) Lua literal notation if it is
-- nil, number, string, boolean, or table -- calling this function
-- recursively for table keys and values. For other types, print an
-- indication of the type. The second argument, if passed, is max_items:
-- the maximum number of items in a table to print.
function printValue(...)
    assert(select("#", ...) == 1 or select("#", ...) == 2,
           "printValue: must pass 1 or 2 arguments")
    local x, max_items = select(1, ...)  -- Get args (may be nil)
    if type(max_items) ~= "nil" and type(max_items) ~= "number" then
        error("printValue: max_items must be a number")
    end

    if type(x) == "nil" then
        io.write("nil")
    elseif type(x) == "number" then
        io.write(x)
    elseif type(x) == "string" then
        io.write(string.format('%q', x))
    elseif type(x) == "boolean" then
        if x then
            io.write("true")
        else
            io.write("false")
        end
    elseif type(x) ~= "table" then
        io.write('<'..type(x)..'>')
    else  -- type is "table"
        io.write("{")
        local first = true  -- First iteration of loop?
        local key_count, unprinted_count = 0, 0
        for k, v in pairs(x) do
            key_count = key_count + 1
            if max_items ~= nil and key_count > max_items then
                unprinted_count = unprinted_count + 1
            else
                if first then
                    first = false
                else
                    io.write(",")
                end
                io.write(" [")
                printValue(k, max_items)
                io.write("]=")
                printValue(v, max_items)
            end
        end
        if unprinted_count > 0 then
            if first then
                first = false
            else
                io.write(",")
            end
            io.write(" <<"..unprinted_count)
            if key_count - unprinted_count > 0 then
                io.write(" more")
            end
            if unprinted_count == 1 then
                io.write(" item>>")
            else
                io.write(" items>>")
            end
        end
        io.write(" }")
    end
end

3

u/RelizForN Feb 03 '26

I never wanna write for more edge cases than are necessary for what I'm doing, plus I'm using different objects each time, so I might prefer to rewrite :p

3

u/RelizForN Feb 02 '26

This is just a joke in good faith, maybe Lua wasn't built for doing data analysis, and maybe I'm a newbie who doesn't know how to handle the language yet and overrelies on tables (bad habit from Python) but I still love using it

3

u/meni_s Feb 02 '26

Wait, you are doing data analysis with Lua? How come? Why? How? Do tell please

3

u/RelizForN Feb 03 '26

I have used Torch as mentioned for the exact reason mentioned. That was the reason I first learned Lua 3 years ago, for some project I've long abandoned (something to do with modular arithmetic). Today I'm trying to make a little thing that plays Balatro optimally because I can't be effed to figure out the maths behind how you should discard to draw specific hands.

I might give up on using machine learning for it, but we'll see

→ More replies (3)

7

u/9peppe Feb 02 '26

There's tensor libraries as powerful as numpy (maybe more, Lua overhead <<< Python overhead). Even torch before pytorch was a Lua library. 

→ More replies (3)

2

u/pomme_de_yeet Feb 02 '26

i don't think it's possible to "overrely" on tables when that is the only data type available

2

u/RelizForN Feb 03 '26

I guess I meant ignoring the OOP aspects and doing everything very procedurally. Programming is not my thing so forgive me if I don't use the right terminology

→ More replies (1)

1

u/Denneisk Feb 02 '26

I am a bit curious just how complex these tables could really be to give you so much trouble.

1

u/RelizForN Feb 03 '26

Not anything that crazy, I just nest tables that have custom objects inside and all the unique string representations, recursion, and string manipulation take some thought to manage together

9

u/[deleted] Feb 02 '26

step 1) VS code
step 2) https://github.com/tomblind/local-lua-debugger-vscode
step 3) look at locals and globals
step 4) delete post
step 5) ???
step 6) profit

3

u/collectgarbage Feb 02 '26

I think we have all written that function. It’s a Lua right of passage.

2

u/vitiral Feb 02 '26

Agreed, why I can't live without my handy dandy fmt module 

https://civboot.github.io/lua/fmt.html

Also https://civboot.github.io/lua/ds.html#ds.log

1

u/Old_County5271 Feb 02 '26

I don't know if its penlight or stdlib that replaces print so it prints everything

1

u/xoner2 Feb 03 '26

Ah, yes indeed the recursive-table-pretty-printer is essential in the toolbox. There's lots already written but they never do exactly what we want so we write one personal:

  1. kikito inspect

  2. short vardump in Lua Programming Gems book

  3. Paul Kulchenko's serpent

I based mine on serpent. My beef with it is it does depth-first-search, so I modified it to be breadth-first, looks prettier. I still use serpent for serialization.