Procedures and functions
Functions and files · about 7 min
A procedure performs an action. A function also returns a value through Result. Call a function where a value is needed instead of having it secretly write to a form control. This separation makes the calculation easier to test and reuse. A value parameter is a local copy; a const parameter expresses read-only intent; a var parameter allows changes to the caller’s variable.
Local variables exist within the routine and must be initialised before reading. Avoid using global counters that can retain values between button clicks. Define the contract before implementation: accepted inputs, result, and what happens for invalid inputs. A function that divides by a count must define the zero-count case. Here, an empty collection has an explicitly chosen result of zero; a different application might reject it instead.
Key points- Distinguish a returned result from a side effect.
- Choose value, const and var parameters.
- Give every function path a result.
Worked example: function Average(iTotal, iCount: Integer): Double; begin if iCount <= 0 then Result := 0 else Result := iTotal / iCount; end; Average(17,2) returns 8.5 because / performs real division. Average(0,0) returns 0 under the stated contract. The function does not format the result or update a label: the caller decides how to display it.
Using div truncates an integer quotient. Assigning Result only in one branch leaves another path without a defined return value.
Practice: Design a Boolean function IsPass that returns whether a validated mark is at least 50. What are the boundary tests?
Answer: Result := iMark >= 50; with an Integer parameter. Test 49=False, 50=True and 51=True. Validate the 0–100 mark range before calling it, or explicitly include that range in the contract.
Recap: Make a routine’s input and output contract explicit, then test every path.