Functions

A named, reusable block of instructions that takes input (parameters), performs a specific task, and optionally returns a result — the fundamental unit of organisation in code, enabling you to write logic once and use it many times.


What is it?

Without functions, a program is a single long sequence of instructions. If you need to calculate a total in three different places, you copy the calculation three times. If you later discover a bug in that calculation, you fix it in three places — and hope you do not miss one.

Functions solve this. You write the logic once, give it a name, and call it wherever you need it. The logic is defined in one place and executed in many places.1

Every programming language has functions (sometimes called methods, procedures, or subroutines — different names for the same idea). They are the primary way programmers organise code and manage complexity.

In plain terms

A function is a recipe. It has a name (Chocolate Cake). It lists ingredients (parameters). It describes steps (the code inside). It produces a result (return value). You can follow the recipe as many times as you want without rewriting it.


At a glance


How does it work?

Defining a function

You define a function once. The definition includes its name, its parameters (if any), and its body — the instructions to execute when called:2

def calculate_tax(amount, rate):
    tax = amount * rate
    return tax

This function is named calculate_tax. It takes two parameters (amount and rate), multiplies them, and returns the result.

Calling a function

Calling (or invoking) a function executes its body with specific values for the parameters:

vat = calculate_tax(100, 0.077)    # vat is now 7.7
income_tax = calculate_tax(5000, 0.15)    # income_tax is 750

Same function, different inputs, different outputs. The logic is written once and reused.

Parameters and return values

Parameters are the inputs a function expects. They are placeholders — the actual values are provided when the function is called.

Return values are the outputs. A function can return one value, multiple values (in some languages), or nothing at all (a function that only performs an action, like printing to the screen).

LanguageDefining a function
Pythondef greet(name): return "Hello, " + name
JavaScriptfunction greet(name) { return "Hello, " + name; }
JavaString greet(String name) { return "Hello, " + name; }

Think of it like...

A vending machine. You insert specific coins (parameters), the machine performs internal operations (the function body), and a specific product comes out (the return value). The machine’s internal workings are hidden — you only interact through the input slot and the output tray.

Scope

Variables created inside a function are local to that function. They exist only while the function runs and disappear when it returns. This boundary is called scope.3

def greet():
    message = "Hello"    # local variable — exists only here
    return message
 
# message does not exist here — it is out of scope

Scope is a direct application of separation-of-concerns. Each function manages its own data independently. Variables in one function cannot accidentally interfere with variables in another.

Composition

Functions can call other functions. This is composition — building complex behaviour from simple, reusable pieces:4

def format_name(first, last):
    return first + " " + last
 
def greet(first, last):
    full_name = format_name(first, last)
    return "Hello, " + full_name
 
greet("Marie", "Dupont")    # "Hello, Marie Dupont"

greet calls format_name. Each function does one thing well. Together, they produce the desired result.


Why do we use it?

Key reasons

1. Reusability. Write once, use anywhere. No duplicated logic means fewer bugs and easier maintenance.

2. Readability. calculate_tax(amount, rate) communicates intent immediately. The alternative — five lines of inline arithmetic — does not.

3. Testability. A function with defined inputs and outputs can be tested in isolation. You can verify that calculate_tax(100, 0.077) returns 7.7 without running the entire program.

4. Abstraction. Functions hide complexity. The caller does not need to know how the tax is calculated — just that it is. This is abstraction-layers applied at the code level.


When do we use it?

  • Every time logic will be used more than once
  • Every time a block of code does a distinct, nameable thing
  • Every time you want to make code easier to read by replacing a block of instructions with a descriptive name
  • Every time you want to test a piece of logic in isolation

Rule of thumb

If you can give a block of code a name that describes what it does (not how), it should probably be a function. If you find yourself copying and pasting code, it should definitely be a function.


How can I think about it?

The recipe card

A function is a recipe card in a cookbook. The card has a title (function name), a list of ingredients (parameters), a set of instructions (body), and a result (return value).

You can follow the recipe whenever you want — for dinner tonight, for a party next week, for a friend who asks for the recipe. You write it once. You follow it as many times as needed. If you discover a better technique, you update the recipe in one place and every future use benefits.

The specialist

Think of a function as a specialist you can call. Instead of calculating tax yourself every time, you call the tax specialist (function). You give them the numbers (parameters), they do the work (body), and they hand you the result (return value).

You do not need to know how they calculate it — that is their concern, not yours. This is the same principle as separation-of-concerns: each specialist handles their own domain.


Concepts to explore next

ConceptWhat it coversStatus
variablesThe data functions receive and producecomplete
control-flowThe decisions and loops inside functionscomplete
separation-of-concernsThe principle functions embodycomplete
programming-paradigmsHow functions are used in different paradigmscomplete

Check your understanding


Where this concept fits

Position in the knowledge graph

graph TD
    SD[Software Development] --> FN[Functions]
    SD --> VAR[Variables]
    SD --> CF[Control Flow]
    FN -.->|uses| VAR
    FN -.->|contains| CF
    FN -.->|embodies| SoC[Separation of Concerns]

    style FN fill:#4a9ede,color:#fff

Related concepts:

  • variables — functions receive variables as parameters and produce them as return values
  • control-flow — most functions contain conditionals and loops
  • separation-of-concerns — functions isolate logic into independent, reusable units

Sources


Further reading

Resources

Footnotes

  1. Abelson, H. & Sussman, G. (1996). Structure and Interpretation of Computer Programs. 2nd ed. MIT Press.

  2. TripleTen. (2024). Basic Coding Concepts. TripleTen.

  3. Codecademy. (2024). Overview of Conditionals, Functions, and Scope. Codecademy.

  4. The principle of function composition is central to both mathematics and programming. Bird, R. (2014). Thinking Functionally with Haskell. Cambridge University Press.