Lua Question

I’m trying to optimize some code that would benefit from something akin to but probably not quite proper recursion.

There are two issues here.

  1. I’d like to know if it’s possible to table up functions as I’m illustrating in this code example.
  2. I need to know how deep I can go with this? What’s the “maxDepth” limit (if there is one) before I run into some sort of internal error in Lua.

This is just example code showing the structure I’m thinking of using. It’ll run (if it works) but it’s not my actual code. The validation routines are already written and some of them are pages long so it’d be a distraction to show them. It’s solely the two functionality issues I listed that concern me here.

local maxDepth, f, p = 10, {}, {}
p[1]  = function(x) print("Process first case validation"   return (x + 1)) end
p[2]  = function(x) print("Process second case validation"  return (x + 1)) end
p[3]  = function(x) print("Process third case validation"   return (x + 1)) end
p[4]  = function(x) print("Process fourth case validation"  return (x + 1)) end
p[5]  = function(x) print("Process fifth case validation"   return (x + 1)) end
p[6]  = function(x) print("Process sixth case validation"   return (x + 1)) end
p[7]  = function(x) print("Process seventh case validation" return (x + 1)) end
p[8]  = function(x) print("Process eighth case validation"  return (x + 1)) end
p[9]  = function(x) print("Process ninth case validation"   return (x + 1)) end
p[10] = function(x) print("Process tenth case validation"   return (x + 1)) end
function f.VariableCountFunction(x)
	if x <= maxDepth then
		local y = p[x] -- Will this actually execute the referenced function?
		f.VariableCountFunction[y]
	else
		print("No positive cases found")
	end
end

it is, everything is a table (array) in lua. p is just a table of functions in your case

p[1] is mostly the same as p["functionname1"], one is (a little bit) easier to access programmatically, the other is more easily human readable.

you can keep recursively calling the function until lua runs out of memory. most people would add a sanity depth variable to stop that sort of runaway if they think it might happen.

pretty sure it wont, it just an assignment (ie, y is now the function p[x]).

you probably need to add parentheses to the end so it actually calls the function, plus you need to add another x because youre using it for two purposes (which element of p to call, and what parameter to pass to p[x])

local y = p[x](x)

same for
f.VariableCountFunction[y](y)

if you dont it’ll probably barf on x + 1 as x would be null inside the function

its a sort of weird example though. if youre just checking for recursion depth limit you dont need the table of p functions for that, just roll them into the VariableCountFunction and depending on where you put the print it should count from 1-10 or 10-1.

you’d probably want it at the start or youll never see anything except the game hanging and and an out of memory error. that or the script timer limit will kick in and abort the code.

i think this is correct but someone else will point out any mistakes.

Thanks.

What I’m doing is setting up for a semi-recursive series of functions, user defined, for setting visual rotation cues.

I won’t be able to determine ahead of time how many rules there are.

Essentially this:

If (a series of complex situational checks are true) then indicate it's time to use rotation item 1
elseif (a second series of checks are true) then indicate it's time to use rotation item 2
...
end

I currently have it as a single, fixed-length if/then/elseif/elseif/…/end statement, but I was looking into setting it up so that I go as deep as the number of situations the user has defined elsewhere.

I got close. I’ll take your suggestions and patch them into the stub code I have there and see if I can’t get it to function, just to test the basic structure, then I’ll work on the meaningful code bits.

I appreciate it.

Unless I’m missing something, why don’t you just iterate through your cases?

local cases = { -- each case returns a boolean to indicate success state
	function() print("Process first case validation") return true end,
	function() print("Process second case validation") return true end,
	-- ...
}

function GetRotationItemIndex() -- bad at naming functions
	for i, case in ipairs(cases) do
		if case() then
			return i
		end
	end
end

Because I don’t know how many there will be.

I’m looking at having this be user configurable and I don’t really want to put a hard upper limit on it.

That’s what I’m doing now, of course, but I wrote the basic structure for one class/spec combo and I’ve no idea how many there’ll need to be for a top end on this.

I could just pick a high number - say 30 - and hope for the best - put a hard limit in the documentation - but I’m working on this as a practice project as much as anything else and I’d like to know how to do this sort of dynamic stuff.

ipairs takes the length of the table at runtime, you don’t have to know it in advance

That bit - how many would I need to add if I don’t know how many I need to have stubs for.

I don’t understand what you need stubs for. You can just table.insert new cases into a table when needed.

local cases = {}

table.insert(cases, function()
	-- validation logic in here
	return true -- or false
end)

-- or add a function for it that's accessible throughout your addons namespace
_, ns = ...

function ns.RegisterValidationCase(case)
	table.insert(cases, case)
end

-- and register a case
ns.RegisterValidationCase(function()
	-- validation logic in here
	return true -- or false
end)

That’s pretty much what I’m looking for right there.

That would work just fine.

I wasn’t wedded to the recursion thing. I just needed to be able to dynamically build an indexed table of functions and iterate through execution of each one until I got a “true” answer.

Thanks!

1 Like