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
Function anatomy (click to expand)
graph LR IN[Parameters<br/>ingredients] --> F[Function body<br/>steps] F --> OUT[Return value<br/>result] style IN fill:#e8b84b,color:#fff style F fill:#4a9ede,color:#fff style OUT fill:#5cb85c,color:#fffKey: Data goes in (parameters), logic is applied (body), a result comes out (return value). The function encapsulates the process.
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 taxThis 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 750Same 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).
| Language | Defining a function |
|---|---|
| Python | def greet(name): return "Hello, " + name |
| JavaScript | function greet(name) { return "Hello, " + name; } |
| Java | String 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 scopeScope 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)returns7.7without 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
| Concept | What it covers | Status |
|---|---|---|
| variables | The data functions receive and produce | complete |
| control-flow | The decisions and loops inside functions | complete |
| separation-of-concerns | The principle functions embody | complete |
| programming-paradigms | How functions are used in different paradigms | complete |
Check your understanding
Test yourself (click to expand)
- Explain what a function is using the recipe analogy. Name the three essential parts.
- Describe the difference between defining a function and calling a function. Which happens first?
- Distinguish between a parameter and a return value. Can a function have neither?
- Interpret this: two functions both use a variable called
total. Can they interfere with each other? Why or why not?- Connect functions to abstraction-layers: how does wrapping logic in a function create an abstraction?
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:#fffRelated 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
- SICP — Building Abstractions with Procedures — MIT’s classic text on how functions build abstractions
- Python Functions — Real Python’s comprehensive guide to defining and using functions
- Eloquent JavaScript: Functions — Functions explained through JavaScript with interactive exercises
Footnotes
-
Abelson, H. & Sussman, G. (1996). Structure and Interpretation of Computer Programs. 2nd ed. MIT Press. ↩
-
TripleTen. (2024). Basic Coding Concepts. TripleTen. ↩
-
Codecademy. (2024). Overview of Conditionals, Functions, and Scope. Codecademy. ↩
-
The principle of function composition is central to both mathematics and programming. Bird, R. (2014). Thinking Functionally with Haskell. Cambridge University Press. ↩
