Functions: Reusable Blocks of Work

So far every program on this course has been one continuous script. Real programs are built from functions: named blocks of work that are defined once and called from anywhere. Functions are how a hundred thousand lines stay organised, how teams divide work, and how ideas get names. They are also, not coincidentally, the unit that every decompiler, debugger, and obfuscator operates on.

A function is a recipe card in a kitchen binder. Writing the card is not cooking; the kitchen does nothing when a new card is filed. Cooking happens when someone pulls the card and follows it, and the same card can be followed a hundred times, by anyone, with different ingredients each time. The card's title, "lasagna", is how anyone finds it without reading every step.

Defining is not running

The single most important thing to understand about functions is that they involve two separate moments. Definition is when the function's body is written down and given a name; nothing in the body executes. Calling is when some other code invokes the name; only then does the body run, from the top, once per call. A function defined and never called simply never happens, exactly like the branch of an if that is never taken.

This is also your first taste of a program having structure beyond top-to-bottom flow. Execution now jumps: into the function at a call, back out when it finishes. The Level 0 lesson on the stack showed you the machinery that makes returning to the right place possible.

Why functions exist at all

  • Reuse: logic written once is fixed once. Ten copy-pasted versions of the same computation means ten places for the same bug.
  • Naming: calculateDiscount(price) tells a reader what happens without showing how. The name is compressed understanding.
  • Isolation: a function's internals can change completely while every caller keeps working, as long as inputs and outputs keep their meaning.
  • Testing: a named block with defined inputs and outputs is a thing you can verify on its own, apart from the whole program.

One function, seven spellings

The switcher below defines and calls the same small function in each course language. The keywords differ (function, def, func, static) but every version has the same four parts: a name, a parameter list, a body, and a return.

Feel the problem functions solve

The teaching playground's language deliberately has no functions, and this is the lesson where that starts to hurt. The program below applies the same fee calculation to two orders by copying the logic. Run it, then follow the instruction in the comment at the bottom.

That exercise is the entire argument for functions in miniature. Duplicated logic does not fail loudly when it drifts out of sync; it fails silently, producing plausible wrong answers. A function collapses the duplication to one definition, so there is exactly one place for the logic to be right or wrong.

Two forward pointers for the expert track. First, in most course languages functions are values: they can be stored in variables, passed to other functions, and returned, which is the foundation of callbacks and closures (the scope lesson ahead touches this). Second, the call itself is information. When an attacker maps an unfamiliar binary, the call graph, which function calls which, is the skeleton they hang everything else on, and function inlining in Level 4 is interesting partly because it erases edges from that graph.

Functions and the protection fight

A function name is the densest documentation in a program: verifyLicense, decryptAsset, grantAdmin. A reverse engineer who finds those names has been handed a labelled map. That is why identifier renaming hits function names first and hardest, and why decompilers try so hard to guess names back from behaviour. The function boundary itself also carries meaning, which more aggressive transforms attack: inlining melts the function into its callers, and splitting carves one function into many meaningless fragments. All of that is ahead in Levels 3 and 5; it will make sense because you know what the boundary is worth.

A function is a named block that runs only when called, as many times as it is called. Definition and execution are separate moments. The name and the boundary are both pure information for readers, which is exactly why obfuscation targets them.

Frequently asked questions

Why does the teaching playground not have functions?

Deliberate design. The toy language stays tiny so every lesson's machinery is fully visible, and its missing features are teaching moments: this lesson uses the absence of functions to make you feel the duplication problem they solve. The multilanguage switcher shows real function syntax in eight languages.

What is the difference between a function and a method?

A method is a function that belongs to an object and automatically receives that object when called. The classes lesson later in this level covers exactly how that works. Everything in this lesson, definition versus call, parameters, returns, applies to methods unchanged.

Keep learning

  • Loops: Repeating Work
  • Parameters and Return Values
  • Identifier Renaming: The First Layer, Never the Last
  • Where Values Live: Memory, Stack, and Heap
  • Lua Obfuscator
  • JavaScript Obfuscator
  • Python Obfuscator

All lessons