Last active
February 17, 2021 17:55
-
-
Save mnemnion/1e73d2c1c4c20bba6269f2ede7d5bcdc to your computer and use it in GitHub Desktop.
Sparse multidimensional tables in Lua
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Sparse = {} | |
local function new(dimension) | |
local sparse = {} | |
sparse._dimension = dimension | |
return setmetatable(sparse, Sparse) | |
end | |
function Sparse.__index(sparse, key) | |
if sparse._dimension == 1 then | |
-- clean up and return nil | |
local back, idx = rawget(sparse, "_back"), rawget(sparse, "_idx") | |
rawset(sparse, "_back", nil) | |
rawset(sparse, "_idx", nil) | |
if back == nil then | |
return nil | |
end | |
repeat | |
rawset(back, idx, nil) | |
back, idx = rawget(back, "_back"), rawget(back, "_idx") | |
until back == nil | |
return nil | |
else | |
-- provisionally create a Sparse table | |
local new_sparse = new(sparse._dimension - 1) | |
rawset(new_sparse,"_back", sparse) | |
rawset(new_sparse, "_idx", key) | |
rawset(sparse, key, new_sparse) | |
return new_sparse | |
end | |
end | |
function Sparse.__newindex(sparse, key, value) | |
if sparse._dimension > 1 then | |
-- as a refinement, this could be allowed for sparse | |
-- tables of the correct dimension | |
-- an interesting exercise! | |
error("attempt to assign value to inner value of " | |
.. sparse._dimension .. "-dimensional sparse table") | |
end | |
-- reify the intermediate tables | |
local back, idx = rawget(sparse, "_back"), rawget(sparse, "_idx") | |
rawset(sparse, "_back", nil) | |
rawset(sparse, "_idx", nil) | |
if back == nil then | |
rawset(sparse, key, value) | |
return | |
end | |
repeat | |
local back_back, back_idx = rawget(back,"_back"), rawget(back, "_idx") | |
rawset(back, "_back", nil) | |
rawset(back, "_idx", nil) | |
back, idx = back_back, back_idx | |
until back == nil | |
if value == nil then return nil end | |
rawset(sparse, key, value) | |
end | |
return new |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment