See all glossary terms

Functional Programming

Functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. It's often considered a declarative programming paradigm, which means programming is done with expressions or declarations instead of statements.
Functional programming is based on the following principles:
  • First-class functions: Functions are treated as first-class citizens, meaning they can be passed as arguments to other functions, returned as values from other functions, and assigned to variables.
  • Pure functions: Functions that always return the same output for the same input and have no side effects. This makes them easier to test and reason about.
  • Immutable data: Data is immutable, meaning it cannot be changed after it's created. Instead of modifying existing data, functional programming creates new data structures.
  • Higher-order functions: Functions that can take other functions as arguments or return them. This allows for the creation of more abstract functions that can work with different types of data.
Functional programming is often considered very different from imperative programming and object-oriented programming, but in reality, the same features can be found in both, just expressed differently.
Let's observe some of the features of object oriented programming, and see how they can be expressed in functional programming:
In functional programming, you can use data structures to represent objects. For example, instead of creating a Person class with properties and methods, you can represent a person as a dictionary:
func create_person(name: String, age: int) -> Dictionary:
    return {
        "name": name,
        "age": age
    }
You can also use encapsulated functions to work with this data structure:
func say_name(person: Dictionary) -> String:
    return "I am " + person["name"]

func create_person(name: String, age: int) -> Dictionary:
    var person := {
        "name": name,
        "age": age,
        "say_name": say_name.bind(person)
    }
    return person
Inheritance is also possible:
func create_student(name: String, age: int, grade: int) -> Dictionary:
    var student := create_person(name, age)
    student["grade"] = grade
    return student
As well as composition:
func augment_student(student: Dictionary) -> Dictionary:
    student["study"] = func(subject: String) -> String:
        return student["name"] + " is studying " + subject
    return student
In GDScript, those functions are a bit sub-par because we wouldn't get the benefits of type checking and autocompletion. But in a functional language like Haskell, those functions would be much more powerful.