You might want a function to behave a bit differently depending on the arguments you give it. Or maybe you want a function to call some other function after running its task.
For instance, sorting a list of items is a very common task. But there are also many different sorting algorithms, each with its own advantages and disadvantages.
So you might have some intermediate function to handle processing the data and another that handles the actual sorting.
Because functions can be treated like data, they can be passed as into other functions just as you would a normal argument.
local function someFunction(numList, func1, func2)
local rand = math.random(2)
if rand == 1 then
func1(numList)
else
func2(numList)
end
end
local function printSum(numList)
local sum = 0
for _, v in ipairs(numList) do
sum = sum + v
end
print(sum)
end
local function printProduct(numList)
local product = 1
for _, v in ipairs(numList) do
product = product * v
end
print(product)
end
local numberList = {1, 2, 4, 8, 16}
someFunction(numberList, printSum, printProduct)
First we define a primary function that performs some task. In this case, just choose a random number. We give it two more functions which, one of which will be run, depending on the result.
Because the result might not be known ahead of time or we might not know when the main function will be completed, we can supply the function argument to be invoked by the main function.
Returning a Function
Just like functions can be passed as arguments, functions can also be returned from a function.
For example, models and parts require a different method of moving. So we can create a “getter” function that returns the proper move function depending on the object type.
local objectList = {}
--------just initilization stuffs------
do
local model = Instance.new("Model")
local modelPart = Instance.new("Part")
modelPart.Position = Vector3.new(5, 5, 0)
modelPart.Anchored = true
modelPart.Parent = model
model.PrimaryPart = modelPart
model.Parent = game.Workspace
local part = Instance.new("Part")
part.Position = Vector3.new(-5, 5, 0)
part.Anchored = true
part.Parent = game.Workspace
objectList[1] = model
objectList[2] = part
end
--------------------------------------
local moveAmount = Vector3.new(0, 0, -0.25)
local runTimeLength = 10
local function moveModel(model)
model:TranslateBy(moveAmount)
end
local function movePart(part)
part.Position = part.Position + moveAmount
end
local function getMoveFunction(object)
if object.ClassName == "Model" then
return moveModel
else
return movePart
end
end
local stopTime = tick() + runTimeLength
while tick() < stopTime do
for _, object in ipairs(objectList) do
local tempFunction = getMoveFunction(object)
tempFunction(object)
end
task.wait()
end
Because models are made of a collection of parts that need to move and rotate as a group, we cannot move just one part. But trying to move all parts by computing their translation and orientation is error prone.
So the model object provides several methods to move or rotate the entire model as a whole. In line 27, the ‘TranslateBy’ method is one such method.
On the other hand, parts can be be moved directly just by setting its position.
Okay, but why can’t we just use an if statement and call the function directly?
Because this a bad contrived example, that’s why. Now stop interrupting me so we can get to the part where this all comes together and makes sense.