1
\$\begingroup\$

I'm learning Lua for about a week now and I've built (I hope) a function to print any type in Lua. As I'm new to Lua I don't quite understand:

  • if there is a more succinct way to achieve this
  • if there is a standard way to print nested tables
  • if there are any cases the function doesn't cover
function printAnyLuaType(AnyLuaType, identationSpaces, identationLevel)

    function printTable(tableToPrint)
    --recursively print a table indenting
        for index, value in pairs(tableToPrint) do
            depperIdentation = currentIdentation .. identationToAppend
            if type(value) == 'table' then
                print(currentIdentation .. index)
                currentIdentation = depperIdentation
                printTable(value) --call to function
            else
                print(currentIdentation .. index)
                print(depperIdentation .. value)
            end
        end
        shallowerIdentation = string.sub(currentIdentation, 1, #currentIdentation - identationSpaces)
        currentIdentation = shallowerIdentation
    end

    --globals for printTable
    AnyLuaType = AnyLuaType or ''
    identationSpaces = identationSpaces or 4
    identationLevel = identationLevel or 0
    identationToAppend = string.rep(' ', identationSpaces)
    currentIdentation = string.rep(identationToAppend, identationLevel)

    --recursively printTable or normal print
    if type(AnyLuaType) == 'table' then
        printTable(AnyLuaType)
    else
        print(AnyLuaType)
    end
end

tableToPrint = {1234, {'a','b','c'}, 5678, ['complains'] = {'ugly', 'fragile'}, {['name'] = 'smith', ['age'] = 10}}

printAnyLuaType(tableToPrint)

--[[
expected output:

1
    1234
2
    1
        a
    2
        b
    3
        c
3
    5678
4
    age
        10
    name
        smith
complains
    1
        ugly
    2
        fragile
--]]
```
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Beware the infinite loop. Also, globals are bad. \$\endgroup\$ Jan 16, 2023 at 18:47
  • \$\begingroup\$ Indeed, an infinite loop is possible if you try to print a table t constructed by the following script: t={}; t[1]=t; printAnyLuaType(t). There is an explanation in the "PiL" book on how to process tables with cycles. \$\endgroup\$
    – ESkri
    Jan 17, 2023 at 7:43

2 Answers 2

2
\$\begingroup\$

This code doesn't cover the case of cyclic tables, but that's fine, we'll view that as out-of-scope.

The style guide recommends that

Variables holding values or objects are typically lowercase

This suggests naming the first parameter anyLuaType instead.

But it's not clear that "any lua type" is really the central problem this code solves, so consider banishing that phrase from identifiers, preferring to put it in explanatory -- comments.

You might instead simply name it function display(value), and document that value can be many things including a table.

Any recursive function will have a base case plus recursive code that reduces the input problem to simpler problem(s). Up in the mainline you check for type table, which seems an odd place to put the check. And then (DRY) we need more checking within the function.

Consider expanding the contract so the function is responsible for distinguishing the base case. Also, rather that fix the "depper" typo, introducing a brief indent helper would be convenient:

indentSpaces = 4

function indent(level)
    io.write(string.rep(' ', level * indentSpaces))
end

function display(value)
    displayRecursive(value, -1)
end

function displayRecursive(value, level)
    if type(value) ~= 'table' then
        indent(level + 1)
        return print(value)
    end

    for index, value in pairs(value) do
        displayRecursive(index, level)
        displayRecursive(value, level + 1)
    end
end

This appears to be a more succinct way of achieving your expected output.

\$\endgroup\$
1
\$\begingroup\$

if there is a more succinct way to achieve this

No.

if there is a standard way to print nested tables

Your way is the standard way.

if there are any cases the function doesn't cover

You can not distinguish between boolean value true and string"true", the same for nil.

One more note:
Try to use local variables instead of globals (currentIdentation, depperIdentation).

\$\endgroup\$
2
  • 1
    \$\begingroup\$ While this is an acceptable answer, it is not a good answer. It would help if you provided more explanations. \$\endgroup\$
    – pacmaninbw
    Jan 16, 2023 at 13:57
  • \$\begingroup\$ @pacmaninbw - What exactly needs to be explained? \$\endgroup\$
    – ESkri
    Jan 17, 2023 at 7:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.