2

I currently have this code, but I feel this can be optimized much better:

local config = {
    val = 1,
    background = {
        foo = 5,
        textures = {
            bar = 'okay',
            layers = {
                alpha = 1,
                color = {
                    red = 255,
                    blue = 0,
                    green = 100
                }
            }
        }
    },
    sub = {
        val = 5,
        foo = {
            val = true,
            bar = {
            }
        }
    }
}

local function set_config(...)
    local arg = {...}
    if type(arg[1]) == 'table' then
        table.extend(config, arg[1])
    elseif #arg == 2 then
        if type(arg[2]) == 'table' then
            table.extend(config[arg[1]], arg[2])
        else
            config[arg[1]] = arg[2]
        end
    elseif #arg == 3 then
        if type(arg[3]) == 'table' then
            table.extend(config[arg[1]][arg[2]], arg[3])
        else
            config[arg[1]][arg[2]] = arg[3]
        end
    -- And now for the 4th time. This is starting to get way to repetitive
    elseif #arg == 4 then
        if type(arg[4]) == 'table' then
            table.extend(config[arg[1]][arg[2]][arg[3]], arg[4])
        else
            config[arg[1]][arg[2]][arg[3]] = arg[4]
        end
    -- And for what I try to achieve, I should continue this elseif's until indefinite
    end
end
-- And this should go as deep into the table as I want to

Now I can do

set_config('val', 3)
set_config('sub', {
    foo = false
})

But I want to go as deep into the table without the limit I have now with the set_config

So I could do

set_config('background', 'textures', 'layers', 'medium', 'color', 'red', 255)

And for clarification, the table.extend

function table.extend(t1, t2)
    for k, v in pairs(t2) do
        if (type(v) == "table") and (type(t1[k] or false) == "table") then
            table.extend(t1[k], t2[k])
        else
            t1[k] = v
        end
    end
    return t1
end

I've tried out a few things, but my Lua knowledge is rather limited.

The answer by lhf was almost correct, here is the outcome that works as i wanted it:

local function set_config(...)
    local a={...}
    local n=#a
    local t=config
    if #a == 1 and type(a[1]) == 'table' then
        table.extend(config, a[1])
        return
    end
    for i=1,n-2 do
        local k=a[i]
        t[k]=t[k] or {}
        t=t[k]
    end
    if type(t[a[n-2]]) == 'table' then
        table.extend(t[a[n-1]], a[n])
    else
        t[a[n-1]] = a[n]
    end
end
5
  • It looks like config is acting like the 'root' of the table. What can config have as keys and values? Your example above is suggesting 2 but can it also have arbitrarily many keys? Commented Oct 29, 2013 at 2:48
  • 3
    What are you trying to achieve? Commented Oct 29, 2013 at 2:49
  • config could be a table with an unlimited depth. So it might happen that config has a key like: config.backgrounds.overlay.color.r. Or even deeper. It's variable. What i want to achieve is that i can use the set_config function to set values in the config table as deep as i give the parameters. so set_config('background', 'overlay', 'color', 'r', 255) should be possible aswell Commented Oct 29, 2013 at 3:10
  • 1
    I have updated my original post which hopefully clarifies what i want Commented Oct 29, 2013 at 3:27
  • 2
    Leave the question as it was originally and move your edit to an answer. Commented Oct 29, 2013 at 9:34

2 Answers 2

3

Try this:

local config={}

function set_config(...)
    local a={...}
    local n=#a
    local t=config
    for i=1,n-2 do
        local k=a[i]
        t[k]=t[k] or {}
        t=t[k]
    end
    t[a[n-1]]=a[n]
end

set_config('background', 'textures', 'layers', 'medium', 'color', 'red', 255)

print(config.background.textures.layers.medium.color.red)
Sign up to request clarification or add additional context in comments.

1 Comment

Nevermind the comment i posted here. This works but needed a slight alteration for my needs. Thanks a bunch
1

With some metatable magic, you can get rid of set_config altogether:

local config, config_mt
config_mt = {
    __index = function(t, k)
        t[k] = setmetatable({}, config_mt)
        return t[k]
    end,
}
config = setmetatable({}, config_mt)

config.background.textures.layers.medium.color.red = 255
print(config.background.textures.layers.medium.color.red)

Though there is one downside: After restoring your config from storage you would have to iterate through the structure once in order to apply the metatables again.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.