A Guide to Guard Clauses

What are Guard Clauses?

A guard clause checks a condition with either a return statement or an exception that immediately exits a function. This is helpful because it isolates all special checks and edge cases into separate clauses before the main checks. It should be a “flat” list of conditionals, one after the other.

Why should I use them?

The problem is that with nested conditions, it can get messy really quickly, and it can be difficult to determine the flow of code execution. Guard clauses, on the other hand, neatly simplifies the special cases by isolating them into separate conditions that then end code execution and return a null value if the guard clauses are true.

Example

An example of using guard clauses is with debounces.
Here’s an example of using a debounce in a nested condition:

local debounce = false

local function doSomeStuff()
    if not debounce then
        debounce = true

        -- Do the rest of your stuff here

        debounce = false
    end
end

However, this is messy code and difficult to read, since it depends on a lot of nested conditionals. Let’s improve upon this code using guard clauses:

local debounce = false

local function doSomeStuff()
    if debounce then 
        return 
    end

    debounce = true

    -- Do the rest of your stuff here

    debounce = false
end

Ta-da! The code is significantly easier to read using guard clauses and more easier to follow the code execution.

Conclusion

I hope this helps you understand what guard clauses are and how to use them! If you have any questions/comments, reply to this thread below.

You can even find this tutorial on GitHub here.

16 Likes

I feel your first example is a bit misleading; couldn’t you just as easily have done:

if isDead then
    return 1000
elseif isSeparated then
    return 1500
elseif isRetired then
    return 2000
else
    return 500
end

Maybe it’s not the best example for guard clauses, but they are useful to avoid scoping in more complex functions.

8 Likes

Good point! This and the other example are good examples of using guard clauses.

I think a simpler example would be the classic debounce.

Without guard clause:

local debounce = false

local function doSomeStuff()
    if not debounce then
        debounce = true

        -- Do the rest of your stuff here

        debounce = false
    end
end

And with guard clause:

local debounce = false

local function doSomeStuff()
    if debounce then return end

    debounce = true

    -- Do the rest of your stuff here

    debounce = false
end
4 Likes

I agree with @Autterfly. The first example is misleading, I don’t think anyone uses if statements like that, even if you are a beginner. I think @BanTech’s example is very good. It is something commonly done, not only by beginners but even more advanced scripters. There are many threads out there regarding guard clauses. I don’t see how this one would stand out.

4 Likes

After seeing feedback about the examples, I’ve updated the tutorial to make use of @BanTech’s example of using debounces!

4 Likes