Introduction to Modules and Functions
Erlang code is organized into modules, and every module is simply a text file containing function definitions, compiled independently and identified by its own name. A module groups related functions together the way a toolbox groups related tools, giving you a namespace so that two different modules can each define a function called start/0 without colliding. Functions themselves are the fundamental unit of behavior in Erlang: since Erlang has no loops or mutable variables, virtually all logic is expressed as functions calling other functions, often recursively.
Cricket analogy: A module is like an IPL franchise: Mumbai Indians and Chennai Super Kings can each have a player called 'Kumar' without confusion, because the franchise name disambiguates them, just as a module name disambiguates same-named functions.
Defining Modules
Every Erlang source file must begin with a -module(Name) attribute, and the file itself must be named Name.erl — the compiler enforces this match, so a module declared -module(shopping_cart) has to live in shopping_cart.erl. Compiling with c(shopping_cart) in the shell, or erlc shopping_cart.erl from the command line, produces a shopping_cart.beam file that the BEAM virtual machine loads and executes; nothing runs until that byte-code file exists.
Cricket analogy: Just as a player's registered team must match the jersey they wear on the field — you can't play for Mumbai Indians in a Chennai Super Kings jersey — a -module(shopping_cart) declaration must match the file shopping_cart.erl exactly.
-module(shopping_cart).
-export([new/0, add_item/2, total/1, greet/1, greet/2]).
new() ->
[].
add_item(Cart, {Name, Price}) ->
[{Name, Price} | Cart].
total(Cart) ->
lists:foldl(fun({_Name, Price}, Sum) -> Price + Sum end, 0, Cart).
greet(Name) ->
io_lib:format("Hello, ~s!", [Name]).
greet(Name, Title) ->
io_lib:format("Hello, ~s ~s!", [Title, Name]).Function Clauses and Arity
A single function name can have multiple clauses, each with a different pattern in its head, and Erlang tries each clause in order until one matches the arguments — this is how classify(0) -> zero; classify(N) when N > 0 -> positive; classify(_) -> negative. selects behavior without an if/else chain. Crucially, a function's identity in Erlang is the pair name/arity, so greet/1 and greet/2 are treated as completely unrelated functions even though they share a name, which is why you'll see them referenced as greet/1 in documentation and error messages.
Cricket analogy: Selecting a bowler for the next over is like Erlang trying function clauses in order: the captain checks conditions — is it a pace-friendly pitch, is a lefty batting — and picks the first bowler whose matching condition fits, just as classify/1 tries each clause top to bottom.
In Erlang documentation and error messages you'll always see functions written as name/arity, such as greet/1 or lists:map/2 — the arity is not optional trivia, it's part of the function's identity, so greet/1 and greet/2 can have completely different bodies and behavior.
Exporting and Calling Functions
The -export([Name/Arity, ...]) attribute lists which functions are visible outside the module; anything left off that list is private and can only be called by other functions inside the same file, giving you a clean public API similar to how a library exposes only certain headers. Calling a function from outside its own module always requires the qualified form Module:Function(Args), such as lists:reverse(L) or shopping_cart:add_item(Cart, Item), whereas calls within the same module can omit the module prefix.
Cricket analogy: The -export list is like the playing XI announced before a match — only those 11 named players can take the field, while the rest of the squad stays in the pavilion, unreachable to the opposition, just as unexported functions stay unreachable outside the module.
Calling an unexported (private) function from another module, or getting the arity wrong, produces an undef error at runtime rather than a compile-time warning in the shell — always double check your -export list matches exactly what you intend other modules to call.
- Every .erl file must declare -module(Name) matching its filename, and compiles to a Name.beam file.
- Functions are identified by name/arity together — foo/1 and foo/2 are unrelated functions.
- A function can have multiple clauses; Erlang tries them top to bottom and runs the first one whose pattern matches.
- The -export([Name/Arity, ...]) attribute controls which functions are callable from outside the module.
- Calls to functions in another module require the qualified form Module:Function(Args).
- Functions not listed in -export are private and only callable from within the same module.
- Compiling with c(Module) in the shell or erlc Module.erl produces the loadable .beam file.
Practice what you learned
1. What must be true about a file that declares -module(shopping_cart)?
2. Why are greet/1 and greet/2 considered different functions in Erlang?
3. What happens if a function has three clauses and the arguments match the pattern of the second clause only?
4. How do you call add_item/2 from a module other than shopping_cart?
5. What is required for other modules to call a function defined in your module?
Was this page helpful?
You May Also Like
Guards and Clauses
How Erlang guards extend pattern matching with safe boolean conditions to express multi-way branching without if/else.
Recursion in Erlang
Why recursion replaces loops in Erlang, and how to write correct, tail-recursive functions that run in constant stack space.
Higher-Order Functions in Erlang
How Erlang treats functions as first-class values, enabling anonymous funs, closures, and the standard library's map/filter/foldl.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics