This is a technique I’ve discovered quite recently, and it has reduced the amount of elseif statements in my code by two times.
In case you didn’t know. If statements are slow. The compiler has to process every possible path your code could go down.
You can replace a lot of elseif statements that compare strings and numbers with a table of functions that are loaded into memory instead. This is going to take less lines, run faster and be easier to read. You can learn by example using the example code below:
--CLASSIC BRANCHED PROGRAMMING
local function SaySomething(emotion,topic)
if emotion == "Angry" then
if topic == "Fruit" then
print("i hate apples!")
elseif topic == "Candy" then
print("i hate chocolate!")
end
elseif emotion == "Happy" then
if topic == "Fruit" then
print("i love apples!")
elseif topic == "Candy" then
print("i love chocolate!")
end
end
end
SaySomething("Angry","Fruit")
--BRANCHLESS METHOD
local t = {} --keep this loaded into memory so we can overwrite it every time we want to write a "branchless branch"
local function CarAction(car,action)
t = {
VolvoDestroy = function()
volvo:Destroy()
end,
VolvoPaint = function()
volvo.Paint(BrickColor)
end;
HondaDestroy = function()
honda:Destroy()
end;
HondaPaint = function()
honda.Paint(BrickColor)
end;
}
(t[car..action] or function()end)()
--car..action should match one of the entries in the table above, if it doesn't then we run an empty function
end
CarAction("Volvo","Paint")
This isn’t a full replacement for if statements, it’s only a replacement in some cases, and it works exceptionally in those cases.
6 Likes
Saying “If statements are slow” is an over-exaggeration. From my testing using branchless programming makes so little difference it doesn’t matter.
I did some tests that time how long it takes for each method to run the same function and it does it 10 thousand times and averages it out.
Here’s the code
local function time(func,...)
local iterations = 10000 --// 10k
local totalTime = 0
local maxTime = 0
for i = 1,iterations do
local startTime = os.clock()
func(...)
local timeTaken = (os.clock() - startTime)
totalTime += timeTaken
if timeTaken > maxTime then
maxTime = timeTaken
end
end
warn("Total Time: "..totalTime)
warn("Average Time Taken: ".. totalTime/iterations)
warn("Max Time: ".. maxTime)
end
--CLASSIC BRANCHED PROGRAMMING
local function SaySomething1(emotion,topic)
if emotion == "Angry" then
if topic == "Fruit" then
print("i hate apples!")
elseif topic == "Candy" then
print("i hate chocolate!")
end
elseif emotion == "Happy" then
if topic == "Fruit" then
print("i love apples!")
elseif topic == "Candy" then
print("i love chocolate!")
end
end
end
wait(2)
warn("Branched")
time(SaySomething1, "Happy","Candy")
--BRANCHLESS METHOD
local t = {} --keep this loaded into memory so we can overwrite it every time we want to write a "branchless branch"
local function SaySomething2(emotion,topic)
t = {
["Angry"] = {
["Fruit"] = function()
print("i hate apples!")
end,
["Candy"] = function()
print("i hate chocolate!")
end,
},
["Happy"] = {
["Fruit"] = function()
print("i love apples!")
end,
["Candy"] = function()
print("i love chocolate!")
end,
},
}
(t[emotion][topic] or function()end)()
--car..action should match one of the entries in the table above, if it doesn't then we run an empty function
end
wait(2)
warn("Branchless")
time(SaySomething2, "Happy","Candy")
If you see here the difference between branchless and branched code is a minuscule difference.
Average is tiny and even if you look at the extremes, the max time spent, the difference is only in the milliseconds
Even consider the worst-case scenario. Say you have 70 completely random if statements like this
local function SaySomething1(emotion,topic)
if emotion == "Angry" then
if topic == "Fruit" then
print("i hate apples!")
elseif topic == "Candy" then
print("i hate chocolate!")
end
elseif emotion == "edewdwdw2w" then
elseif emotion == "edewdwdw5w" then
elseif emotion == "edewdwdw6w" then
elseif emotion == "edewdwdwd7w" then
elseif emotion == "edewdwdwdw7" then
elseif emotion == "edewdwdwd6w" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "ed6ewdwdwdw" then
elseif emotion == "ede6wdwdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edew6dwdwdw" then
elseif emotion == "edewd6wdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edew5w4dwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwd4wdw" then
elseif emotion == "edewdwdw44dw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "ede4wdwdwdw" then
elseif emotion == "edew4d7dwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewd46dwdw" then
elseif emotion == "edewd54dwdw" then
elseif emotion == "edewd4dwdw" then
elseif emotion == "edew2wd4wdw" then
elseif emotion == "edewdwdw4dw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "e4dewdwdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "ed4ewdwdwdw" then
elseif emotion == "ede4wdwdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edew4dwdwdw" then
elseif emotion == "edewd4wdwdw" then
elseif emotion == "edewdw4dwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwd4wdw" then
elseif emotion == "edewdwdw4dw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwdwd4w" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edew6dwdwdw" then
elseif emotion == "edewd6wdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdw7dwdw" then
elseif emotion == "edewdwd7wdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edyewdwdw7dw" then
elseif emotion == "edeywdwdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewydwdwdw" then
elseif emotion == "edewdywdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwydwdw" then
elseif emotion == "edewdwdywdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwdwydw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edeewdwdwdw" then
elseif emotion == "edewedwdwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdewdwdw" then
elseif emotion == "edewdwedwdw" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwdewdw" then
elseif emotion == "edewdwdwedw" then
elseif emotion == "edewdwdwdew" then
elseif emotion == "edewdwdwdw" then
elseif emotion == "edewdwdwdwe" then
elseif emotion == "Happy" then
if topic == "Fruit" then
print("i love apples!")
elseif topic == "Candy" then
print("i love chocolate!")
end
end
end
The difference is still so small there is almost no difference.
Do what you want to do but you shouldn’t be discouraged from using if statements. Both are completely fine.
12 Likes
As long as you don’t become a yandere dev you should be fine
2 Likes
This is definitely how it should be done - where you can . But not for efficiency reasons - it is nearly exactly the same as just branching with an if statement - only when you start getting into crazy levels of hundreds of if statements will you notice a difference. The benefit here is solely readability / good code patterns.
1 Like