Figuring out whether a table is empty in Lua

I’m currently working on a tagging system for this website using pandoc, and I’ve decided to take a little break to write about a function I wrote for the system. My tags aren’t ready yet (I don’t have a deduper yet, for example, nor do I have any setup to actually make the tag pages), by the way. I’m just proud of myself for getting this function together:

I’m not sure if is_empty is really a good name for it, because it doesn’t exactly tell you that (or not only that), but whether a table contains only empty tables. I decided to implement it because of the way pandoc implements metadata, and I use that metadata (namely the tags field) to build my tag file that will, hopefully, build my tag index. I could’ve just checked for the emptiness of, say, tags[1][1].c, but I think that’s fragile (what if pandoc changes the structure?) and ugly. Thus, this function. Let’s talk about it.

Obviously, if the thing passed to is_empty isn’t a table, it’s not an empty table. Easy so far.

I needed to check the length of tbl next: if it’s {}, we can go ahead and mark it as empty too. It wasn’t as easy as it looked at first though: I was using #tbl == 0, which only checks for the numerically-indexed keys in tbl. Pandoc eventually has keys like "c" and "t", which aren’t numbers, so my function was returning true on tables that weren’t empty. next() gets the next index of the table (I think; I saw the answer on Stack Overflow and the documentation is sparse), and works with both numerical and other - indexed keys.

Here we go. Into the depths of the table. pairs() recurses through the table, returning keys and values (bound here to k and v).

Another easy one: if v is not a table, it’s something important like 1, "hello", or whatever. So the table isn’t empty.

Same idea as the v typecheck above: if k isn’t a number (the default key-type in Lua), then it’s holding information of some kind. For example, if you have a table that’s something like { junk = {} } I’m assuming you want junk to be an empty table, or you’d set it to nil and delete it. That being said, I might revisit this later if necessary.

I’ve put all the recursion stuff together at the end. I’m not sure if it’s tail recursion, but I don’t really care for this use-case. It works, and that’s good enough for me.

First, we check if we’re looking at the last item in the table. If so, we just check whether it is empty, using the same function we’re building. Otherwise, we look inside the table and if it’s not empty, we return false, or else we keep going with the for loop.

Now just to end everything:

Wrap it all up in the function is_empty, and you’ve got a good way to look inside a table to see if it’s turtles all the way down.