Is there a better way to pass predetermined arguments that are set at runtime?

I have a function that I want to call with a set of predetermined arguments. However, the arguments are set at runtime, so I can’t save the arguments themselves. My current method involves saving a reference to the argument in a table, then running a for loop through it. This feels hacky and inefficient, any suggestions for a better system would be appreciated.

Here’s my an example of what my current code looks like:

local PossibleStates = {
    ["inactive"] = {"Position", "Metastate"},
    ["active"] = {"Position, Metastate, Runtime"},
    ["stopped"] = {"Position, Metastate, Runtime, Reason"},
    ["errored"] = {"Metastate, Runtime"} 
}

local function SetState(State)

    local ThingsToPass = {}
    local PossibleThingsToPass = { -- State, and the values I'm passing are defined seperately at runtime
        ["Position"] = State.Position,
        ["Metastate"] = State.Metastate,
        ["Runtime"] = State.Runtime,
        ["Reason"] = State.Reason
        }

    for i,v in pairs(PossibleStates[State]) do
        table.insert(ThingsToPass, PossibleThingsToPass[v])
    end

    StateSet(table.unpack(ThingsToPass))

end

SetState(State)

You can use an inner function:

function Outer(a, b)
	function Inner(c)
		--a, b, and c, are all accessible here
		return a * b + c
	end

	print(Inner(2))

	a *= 2

	print(Inner(2))
end

Outer(1, 3) --prints 5 then 8
Outer(2, 3) --prints 8 then 14

My main problem is what I pass is set at runtime. I.e., I can’t directly reference it like you’re doing. I’m looking for the best way to work around that. My current method works, but feels hacky. While I appreciate the reply, I don’t see how I can use it for my code.

Are the keys of PossibleThingsToPass always the same? I don’t fully understand your case because function arguments are by definition decided at runtime. Do you mean the signature of the function is unknown at runtime? as in it could be SetState(State, Position, Metastate) or it could be SetState(State, Runtime, Reason)?

You can use varargs to pass dynamic arguments.

SetState looks something like:

local function SetState(...)
PassedArguments = ...
end

That isn’t the same thing because you have to determine the meaning of those arguments based on their position in your code, not at runtime. If you want to have optional arguments you can just pass the PossibleThingsToPass table with as many entries as you see fit, no need to unpack() it.

SetState(State, optionsTable)

Sometimes I need to pass things besides State. But thanks for all your help! Interestingly, I found out putting all of PossibleStates inside of SetState speeds up my code by about ~10%. I have no idea why.

This seems even messier, but it does work. Still open to any better solutions.

I don’t think you’re 100% sure what you’re asking for, maybe it will become clearer as you keep working on it.

I might’ve explained what I’m trying to do badly, sorry if I did and gave you that impression. I need to pass one of any set of arguments, all of which are set at runtime, which limits my options. The code does what I want to achieve, I’m just asking if there’s a better way to do it.

Unfortunately the better way to do it is to not do it. You shouldn’t have a function that looks like this. Its a good sign that your function does too much stuff, can be used to do things it’s not meant to, and doesn’t provide any useful structure to your application. My feeling on this is reinforced by the very generic name SetState, and the fact you’re asking a generic question about the textual construction of the code itself as opposed to what it does or should do, things that wouldn’t be that big of a deal on their own.

This is all example code, I never showed production code because I didn’t feel it was necessary. I don’t want to get into specifics because it isn’t relevant to the question and I’d prefer to keep my code private, but my use case does necessitate using functions like this. I should’ve made that clearer. I’ve edited the original post to make it obvious it isn’t my actual code.

You’ve been really helpful so far, and I agree in most cases this would be a bad practice.