Lua snowflake tables
2023-03-25Imagine building an API in Lua, and you want to give users some object handles. such as handles to files.
You represent the file as a table of various metadata, but you don’t really want the user poking around in it and breaking stuff (Hyrum’s Law or something).
And let’s say we don’t like the Python’s masochistic ideology about asking for forgiveness, so let’s build something more robust than prefixing the private fields with double underscores.
You can use the neat fact that two tables are never equal, unless they are the same table. {} ~= {}
, because both of the {}
expressions create a new, unique table.
So, if you want to manage all files and file handles in your library, you can create a great table of all files like this:
local files = {} -- anticlimactic creation of the great table
Then you could have a file factory function:
function new_file()
local id = {}
local impl_detail = {
name = 'whatever',
}
files[id] = impl_detail
return id
end
The implementation detail of a file is literally unreachable from the user code. To make things even cooler, you can clean up the files automatically by using a weak reference to the key in your grand table:
files = setmetatable({}, {__mode = "k"})
Now, when there are no other references to the id other than the one from the grand table, the file gets GCed.
I like to call these snowflake tables because they are all the same yet unique.