How to turn a loop into a function, with variable script inside the loop?

I often have a complex loop structure that must be applied to various parts of my script, just changing the core of the loop. Ex:

for a=1, 3 do
	for b=a, 3 do
		print(a, b)
	end
end
print('---------')
for a=1, 3 do
	for b=a, 3 do
		print(a+1) --> same loop, other core
		print(b+1)
	end
end

Currently, to achieve this goal, I use the following structure:

local MyFunctions = {}

function MyFunctions.ScriptA(a, b, Arg1, Arg2)
	print(a+Arg1, b+Arg2)
end

function MyFunctions.ScriptB(a, b, Text)
	print(Text, a, b)
end

function MyLoop(FuncName, ...) -- the main loop
	for a=1, 3 do
		for b=a, 3 do
			MyFunctions[FuncName](a, b, ...)	
		end
	end
end

MyLoop('ScriptA', 10, 20)
print('-----')
MyLoop('ScriptB', 'some text')

This will work, and will print the following:

 11 21
  11 22
  11 23
  12 22
  12 23
  13 23
  -----
  some text 1 1
  some text 1 2
  some text 1 3
  some text 2 2
  some text 2 3
  some text 3 3

But I think this structure is very bureaucratic…
So I would like to know if there is a simpler, more objective and elegant way to do this…

Try to utilize the return function

Didn’t get it.
Could you send an example?

When using the return function you are referencing a function as a variable. Basically, a function acts as a variable. Commonly, you will add a variable inside the function with the return in, however, I do not believe you are limited to this. For example


local function returnVar() -- This creates the function
    local printThis = "This will be printed!" -- Creating a new variable
        return printThis -- Here you are giving (or returning) information for whatever is asking
end

print(returnVar()) -- See how this is printing a function? You can tell because it ends with ()

Now it’s your job to adapt what is above to your script. If you need to return multiple values then refer to the article I gave you before :smile:

it would be alot easier to help if i knew what the loops were and how you were trying to combine them.
To my knowledge there isnt a way to pass actual code as a parameter to a function. However i dont see how this is an issue. If all those loops are unrelated then making a function that writes the loop part for you isn’t really doing anything for you. It seems like the same thing just replacing the “for i = 1, 10, 1 do” part with a function name.

Sorry, but your example has nothing to do with my question.
I want to have a single function with the external for/end and send any script to run inside them, as an argument of this function.
The example is in the OP.

Could you maybe tell us what you want to achieve rather than trying to explain it? What your asking for doesn’t make much sense

I edited the OP by putting an actual example that works, but which I find too complex.

local function orangePrint(...) --Outputs orange colored text.
	local a = {...} --arguments
	warn(table.concat(a, " "))
end

local function loopFunction(f, s, e, i, ...) --function, start, end, increment, tuple
	for n = s, e, i do --number = start, end, increment
		f(...)
	end
end

loopFunction(orangePrint, 1, 3, 1, "Hello", "world!")

Instead of passing the function’s name you could pass a direct reference to the function itself.

1 Like

Also, if the inner function doesn’t demand many lines, you can declare the function itself inside the arguments:

local function loopFunction(f, s, e, i, ...) --function, start, end, increment, tuple
	for n = s, e, i do --number = start, end, increment
		f(...)
	end
end

loopFunction(function(a1, a2) print(a1,a2) end, 1, 3, 1, "Hello", "world!")