Question about setting a value as nil in a table

Hello!

Sorry for the confusing title, however I have a question, is it possible to set a value in a table to nil without it actually removing that value?

For example, here’s a blank datastore template for my game:

        data = {
				['MusicIDs'] = defaultMusic;
				['Coins'] = 0;
				['Experience'] = 0;
				['RequiredExperience'] = 100;
				['Stage'] = 0;
				['Gamepasses'] = {};
				['Inventory'] = {
					['Pets'] = {};
					['Accessories'] = {};
					['Crates'] = {};
				};
				['BanInfo'] = {
					['Banned'] = false;
					['ExpiryDate'] = nil; -- here
					['BanReason'] = nil; -- here
				};
			}

In the labeled values, you can see the values are being set to nil, however it actually removes the entry when being printed.

Capture d’écran, le 2020-11-11 à 20.44.39

Is there a way around this without setting the values to a string?

Why do you want to do this? That is the point of removing it. Either set it to a string or use another sentinel value.

2 Likes

I like using a fake, unique value to represent nil in cases where I want to stream changes somewhere (like sharing table indices to clients). Only problem, I cannot normally represent those changes since nil removes keys altogether. Using a string is fine, but it creates an unnecessary edge case, and I run by Murphy’s Law.

Tables work perfectly, since they’re objects!

local NULL = {}

Due to the nature of tables, the equals == operator will only return true in the expression NULL == NULL; it’s an entirely unique value, different from any other value. Just like nil.

I then hook a couple metamethods with a proxy table to use Lua’s nil and my NULL seamlessly:

local p = newproxy(true)
local t = {}

local mt = getmetatable(p)

function mt.__index(self, index)
    local v = t[index]

    if v == NULL then
        return nil
    else
        return v
    end
end

function mt.__newindex(self, index, value)
    t[index] = value == nil and NULL or value
end

As for serializing this to a DataStore, unfortunately JSON doesn’t have this functionality. You’ll have to use trivially null values (like -1, or empty string) but that opens some ambiguity.

3 Likes