See all glossary terms

Pure Functions

We call "pure function" any function that:
  1. Always returns the same output when given the same arguments.
  2. Doesn't have any side effects.
In other words, they are functions that don't automatically change the data in your program, which limits the risk of bugs and makes functions easier to test programmatically.
Let's look at some examples of pure and impure functions.

Examples of impure functions

Impure functions are the opposite of pure functions: they may overwrite data directly from within the function code, or their output depends on external context, not just their arguments.
It's sometimes necessary to have impure functions, such as reading or writing files or interacting with the user. Here's an example of an impure function that loads and returns the data in a config file:
func get_config() -> ConfigFile:
    var config := ConfigFile.new()
    var result := config.load("user://save_file.cfg")
    if result != OK:
        return null
    return config
If there is no config file at the path user://save_file.cfg, this function will return null. This is what I call inconsistent output: the function's output depends on the existence of a file on the disk.
This second example is a variant of the function above, with side effects. If the config file doesn't exist, the function will create it:
func get_config() -> ConfigFile:
    var config := ConfigFile.new()
    var result := config.load("user://save_file.cfg")
    if result != OK:
        config.save("user://save_file.cfg")
    return config
The risk of side effects is that they can make the program unpredictable. For example, if there's no config file to load, if the operating system prevents your program from writing the config file to the disk, there will be an error.
Side effects and inconsistent output depend not only on files on the disk. They can also be caused by the program's state, the time of day, or the user's input. For example, if you have a function that returns the current date, the output of the function will change every day, even if the arguments are the same:
func get_date() -> String:
    return Time.get_date_string_from_system()
The following function has a side effect because it changes the value of the name variable outside of the function:
var name := "Bilbo"

func set_as_hobbit(toggle_on: bool) -> void:
    if toggle_on:
        name = "Bilbo"
    else:
        name = "Gandalf"
Similarly, if a function reads and returns the value of a variable, it is impure because the output of the function depends on the state of the program:
var name := "Bilbo"

func get_name() -> String:
    return name
Impure functions are necessary, but the more we have, the more complicated our program becomes because functions become increasingly unpredictable or change the program's behavior unexpectedly.

Examples of Pure Functions

Here are some simple examples of pure functions. First, any mathematical function is a pure function. For example:
  • sqrt(x), returns the square root of x.
  • cos(x), returns the cosine of x.
You can also, of course, write your own pure functions. This function calculates and returns the area of a circle:
func calculate_circle_area(radius: float) -> float:
    return PI * pow(radius, 2.0)

See Also

Related terms in the Glossary