Procedures, functions and structured programming
Introduced| English | Meaning |
|---|---|
| subroutines/ˈsʌbruːtiːnz/ | Named groups of instructions that can be called to carry out particular tasks. |
| function/ˈfʌŋkʃn/ | A mapping that assigns exactly one output to each allowed input. |
| procedure/prəˈsiːdʒə/ | A named sequence of instructions that performs a task when called. |
| structured programming/ˈstrʌktʃəd ˈprəʊɡræmɪŋ/ | Organising programs around clear routines and control structures such as sequence, selection and repetition. |
| decomposition/ˌdiːkɒmpəˈzɪʃn/ | The breakdown of a substance or system into simpler components. |
| parameters/pəˈræmɪtəz/ | Values that specify a model or function, or named inputs that a subroutine receives. |
| arguments/ˈɑːɡjuːmənts/ | Values or references supplied to a function or procedure when it is called. |
| signature/ˈsɪɡnɪtʃə/ | In a program interface, the information identifying how a routine is called, such as its name and parameter types, with return information where required by the language or notation. |
| pass by value/pæs baɪ ˈvæljuː/ | pass by value |
| pass by reference/pæs baɪ ˈrefrəns/ | pass by reference |
| global variable/ˈɡləʊbl ˈveərɪəbl/ | A variable declared outside a routine's local scope and accessible wherever the language's program or module scope rules permit. |
| local variable/ˈləʊkl ˈveərɪəbl/ | A variable whose name is accessible only within a particular function, block or other limited scope. |
| scope/skəʊp/ | The region of a program in which a particular name or binding can be accessed. |
A tape of routines anyone could borrow
- By 1951 the EDSAC team in Cambridge kept a library of subroutines on punched paper tape: square roots, printing, logarithms. Any program could read one in and call it.
- The hard part was getting back. David Wheeler's trick, the "Wheeler jump", stored the return address so a routine could return to wherever it had been called from.
- Every function call you write today does the same thing, and every language library descends from that tape.
- This lesson is procedures and functions: how to define them, how to pass values in and out, and how to write one the way Paper 2 marks it.
Procedures and functions
- Structured programming 结构化编程 builds a program from small named subroutines 子程序, each with one job.
- A procedure 过程 is a named block that does an action and returns nothing:
PROCEDURE Greet(Name : STRING) … ENDPROCEDURE, run withCALL Greet("Ada"). - A function 函数 returns a value that becomes part of an expression:
FUNCTION Square(X : INTEGER) RETURNS INTEGER … RETURN X * X … ENDFUNCTION, used asResult ← Square(5) + 1.

A procedure does something; a function hands back a value
The call stack: push on call, pop on return
Calling a subroutine pushes a new frame on top; returning pops it and hands a value back to the caller. The call that is running is always the frame on top.
The key difference between a procedure and a function is that a function:
Difficulty 1/5 · 100 coins + a small bonus on first completion today
A function returns a value (used in an expression); a procedure performs an action and returns nothing.
A function Square(x) returns x * x. What does the call Square(5) return?
Difficulty 2/5 · 140 coins + a small bonus on first completion today
5 × 5 = 25 — the value the function hands back to its caller (the frame popped off the call stack).
Where each is appropriate
- A procedure where the same group of steps is needed at several points: validate an input, print a menu, swap two values. The steps are written once and called by name.
- A function where a single value must be calculated and then used in an expression: a total, a
TRUE/FALSEresult, the larger of two numbers. The return value replaces the call. - Use a subroutine when logic appears in more than one place, when a block has a clear named purpose, when the program is complex enough to need decomposition 分解, or when you want to test one piece on its own.
A good reason to write a subroutine is that:
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Subroutines remove duplication, give a named purpose, and can be tested in isolation.
Parameters, arguments and the interface
- Parameters 参数 are the variables a subroutine declares to receive values; the values the caller supplies are the arguments 实参.
- The header is the first line:
PROCEDURE Name(Param : TYPE)orFUNCTION Name(Param : TYPE) RETURNS TYPE. The interface, or signature 签名, is the name, the parameters in order with their types, and the return type: everything a caller must know. - The return value is what a function passes back with
RETURN.
Match each term to what it means.
Difficulty 2/5 · 140 coins + a small bonus on first completion today
Function vs procedure = returns a value or not; by value vs by reference = copy or original.
Worked example: describe each term in a header
FUNCTION Pass2(Count : INTEGER) RETURNS BOOLEAN.FUNCTION: a subroutine that returns a value.Pass2: the identifier used to call it.Count: the parameter, the identifier that receives the argument passed in.INTEGER: the data type of that parameter.RETURNS BOOLEAN: the data type of the value the function returns. Five parts, one mark each.
In FUNCTION Pass2(Count : INTEGER) RETURNS BOOLEAN, the identifier Count is the ____.
Difficulty 1/5 · 100 coins + a small bonus on first completion today
The parameter receives the argument the caller passes in and is used inside the function like a local variable.
Pass by value and pass by reference
- Pass by value 传值: the routine receives a copy, so changes inside it do not reach the caller. Use it for inputs the routine only reads.
- Pass by reference 传引用: the routine receives a reference to the caller's own variable, so changes do reach the caller. Use it when the routine must update the argument, as in
Swap. - Cambridge writes the mode in the header,
BYVALorBYREF, before each parameter. If neither is written,BYVALis assumed.

A copy, or a link to the caller's variable
Worked example: what is output?
PROCEDURE Adjust(BYREF X : INTEGER, BYVAL Y : INTEGER)
X <- X + Y
Y <- Y * 2
ENDPROCEDURE
A <- 5
B <- 3
CALL Adjust(A, B)
OUTPUT A, B
Xis a reference toA, soAbecomes 8.Yis a copy ofB, so doublingYleavesBat 3.- The output is
8, 3. Had the header saidBYVAL X,Awould still be 5.
In the worked example, what is the value of A after CALL Adjust(A, B)?
Difficulty 2/5 · 140 coins + a small bonus on first completion today
X is passed BYREF, so X ← X + Y adds 3 to the caller's A: 5 + 3 = 8. B stays 3 because Y was a copy.
Local and global variables
- A local variable 局部变量 is declared inside a subroutine and exists only while it runs; a global variable 全局变量 is declared outside and is visible everywhere. The region where a name is visible is its scope 作用域.
- Locals are preferred: the same identifier can be reused elsewhere without a clash, the value cannot be changed accidentally by other parts of the program, the memory is released on return, and the subroutine is self-contained.
- A local is created new on every call, so it cannot carry a value between calls. A routine that builds up a string over repeated calls needs that string to be global, or passed
BYREF.

A global is visible everywhere; a local lives only inside its own subroutine
A local variable exists only inside the subroutine where it is declared, while a global variable is visible everywhere in the program.
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Keeping variables local limits their scope, avoids name clashes, and makes a subroutine testable on its own — globals are best avoided.
Which are benefits of using local variables? Select all that apply.
Difficulty 2/5 · 140 coins + a small bonus on first completion today
A local is created fresh on every call, so it cannot keep a value between calls. That is the one job a global, or a BYREF parameter, does instead.
Turning a procedure into a function
- Change
PROCEDUREtoFUNCTIONand addRETURNS <type>to the header. - Replace the
OUTPUT, or theBYREFparameter that carried the result out, with aRETURNstatement. - Change every call so the returned value is used:
Result ← Unpack(Text)instead ofCALL Unpack(Text, Result).
To convert a procedure into a function you change the header to FUNCTION with RETURNS, replace the OUTPUT with RETURN, and change the calls to use the returned value.
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Three changes, three marks: the header, the RETURN, and the calls.
Worked example: writing a module for Paper 2
- A global array
Score : ARRAY[1:50] OF INTEGERholds test scores. Write a functionCountAbove(Limit : INTEGER)that returns how many scores are greater thanLimit.
FUNCTION CountAbove(BYVAL Limit : INTEGER) RETURNS INTEGER
DECLARE Index, Count : INTEGER
Count <- 0
FOR Index <- 1 TO 50
IF Score[Index] > Limit THEN
Count <- Count + 1
ENDIF
NEXT Index
RETURN Count
ENDFUNCTION
- The scheme awards a mark per feature: the header with parameter and return type, the local declarations, the counter initialised before the loop, the loop over every element, the condition with the right comparison, the update inside it, the constructs closed, and one
RETURNafter the loop. - An unfinished module still scores for every correct part, so write all of them.

Each part of a module answer carries its own mark
Put the parts of a Paper 2 module answer in the order they are written.
Difficulty 3/5 · 200 coins + a small bonus on first completion today
Header, declare, loop, condition, update, return. Each part is a mark, even if another part is wrong.
Marks that slip away
- A routine that must change the caller's variable needs
BYREFin its header; without itBYVALis assumed and the change is lost. - A function has one
RETURN, after the loop, andENDFUNCTION. ARETURNinside the loop ends it on the first element. DECLAREevery local, and initialise a counter or total to 0 before the loop.- "Efficient pseudocode" means moving work that does not change out of the loop, stopping a search at the first match, and not repeating a call whose result could be stored.
To make a loop more efficient, a value that does not change with the loop counter should be:
Difficulty 1/5 · 100 coins + a small bonus on first completion today
Hoisting a loop invariant out avoids recomputing the same value on every iteration.
You've got it
- a procedure does an action and is
CALLed; a function returns a value used in an expression - the header names the routine, its parameters with types and the return type; arguments are the values passed in
- BYVAL passes a copy (the default); BYREF lets the routine change the caller's variable
- prefer local variables; a local is new on every call, a global keeps its value
- a Paper 2 module: header, declarations, initialisation, loop, condition, update, closed constructs, one
RETURN