Procedures and Functions
Procedures and Functions: Overview
- Procedures: declaring and calling
- Parameters
- Local variables
- Scope
- Order of declarations
- Parameter modes: In and Out
- Structure charts
- Parameter mode: In Out
- Parameter modes: why
- Functions
- Terminology: procedures, functions, methods, routines
Declaring and Calling a Procedure
- Example - a procedure that prints 2 lines:
procedure demo is
procedure printlines is
begin
put("------------------");
put("------------------");
end printlines;
begin
printlines;
-- do something
printlines;
end demo;
Structure is same as main
Nested procedure
Can have params
Procedure with Parameters
- Example - a procedure that prints n lines:
procedure demo is
procedure printlines(numLines, numChars: Natural; c: char) is
begin
for i in 1 .. numLines loop
for j in 1 .. numChars
put(c);
end loop;
new_line;
end loop;
end printlines;
begin
printlines(2, 20, '-');
-- do something
printlines(3, 20, '*');
end demo;
Procedures can, of course, have local variables
Procedure with a Local Variable
- Example - a procedure that prints n or n+1 lines:
procedure demo is
procedure printlines(n: Natural) is
limit: Natural := n; -- a local variable
begin
if n mod 2 = 1 then -- n is odd
limit := n + 1;
end if;
for i in 1 .. limit loop
put("------------------");
end loop;
end printlines;
numlines: Natural := 2;
begin
printlines(numlines);
-- do something
printlines(numlines + 1);
end demo;
We need to define the scope of a declaration
Scope
- The scope of a declaration is
- the set of statements over which the declaration is visible (to
the ocmpiler)
- The scope of a declaration is
- From the declaration
- to the end statement associated with the declaration section containing the
declaration
- What is scope of limit, of numlines, of printlines
Order of Declarations
- Ada requires declaration before use
- Consequently, declarations usually go in this order:
- Constants
- New types and/or subtypes
- Procedures and functions
- Variables for main routine
- Example:
procedure main is
MaxValue: constant Natural := 10;
subtype MyRange is Integer range 1 .. MaxValue;
procedure p(m: MyRange) is
someLocal: Natural;
begin
...
end p;
procedure q is begin
p(3);
end q;
v1, v2: Natural; -- Variables for main must go here
m1, m2: MyRange;
begin -- main
...
end main;
All procedures must be declared above where they are called
Global Variables
- Do NOT declare your main variables like this:
procedure main is
MaxValue: constant Natural := 10;
subtype MyRange is Integer range 1 .. MaxValue;
m1, m2: MyRange; -- Variables for main should NOT go here
procedure p(m: MyRange) is
someLocal: Natural;
begin
...
m1 := 2 * m2;
...
end p;
procedure q is begin
p(3);
end q;
begin -- main
q;
end main;
where are v1, v2, m1, m2 visible?
v1, v2, m1, m2 are global to p
Global variable definition: A variable is global to an entity if it is
visible in the entity but not declared in it
Globals make debugging difficult
- They increase coupling
- Discussed later
IMPORTANT: All communication with a procedure (or function) must occur through the
parameter list!!!
Parameter Modes - In and Out Modes
- Parameters have modes
- Modes allow programmer to specify direction of information flow
- In: from caller to called
- Out: from called to caller
- In Out: from caller to called and back
- We use structure charts to show direction of information flow
Structure Charts
- Top box represents problem
- Child boxes represents steps needed to solve parent problem
- Continue to make children until each step/box is doable
- Show information flow on lines between parents and children
- Example - input a natural n and print sum of 1..n and sum of squares of 1..n
- Can use structure chart to decide how to break program into procedures
Example with In Mode and Out Mode
- Example - a procedure that calculates and returns
- sum of 1 .. n
- sum of squares for 1 .. n
procedure demo is
procedure calcs(n: in Natural; s, ssq: out Natural) is
begin
s := 0;
ssq := 0;
for i in 1 .. n loop
s := s + n;
ssq := ssq + n**2;
end loop;
end printlines;
n, sumUpToN, sumSqUpToN: Natural;
begin
get(n);
calcs(n, sumUpToN, sumSqUpToN);
put(sumUpToN);
put(sumSqUpToN);
end demo;
Default parameter mode is: ???
Another example: use procedures and functions to sum and count positives, etc.:
sumcountprocs.adb
and
prettified
Example with In Out Mode Parameters
- In Out mode: pass information from caller to called and back
- Example - keep a running sum of i and i**2:
procedure demo is
procedure calcs(n: Natural; s, ssq: in out Natural) is
begin
s := s + n;
ssq := ssq + n**2;
end printlines;
n, sumUpToN, sumSqUpToN: Natural;
begin
get(n);
sumUpToN := 0;
sumSqUpToN := 0;
for k in 1 .. n loop
calcs(k, sumUpToN, sumSqUpToN);
end loop;
put(sumUpToN);
put(sumSqUpToN);
end demo;
Why Parameter Modes
- Increased flexibility
- Better error checking
- Allow/require programmer to specify information about how a parameter is to be used
- Compiler verifies that the mode is consistent with the code
- Modes are a contract between caller and called
- In: is requirement for caller
- Out: is requirement for called
- In Out: is requirement for both
Compiler Mode Checks
- In mode parameters are treated like constants in the procedure:
- No assignment to in mode parameters
- No passing an in mode parameter to a procedure that
expects an out or in out parameter
- Out mode parameters must be assigned a value
- Examples:
procedure foo1(i: in Integer) is
begin
I := 3; -- COMPILATION ERROR
end foo1;
procedure foo2(o: out Integer) is
begin
null;
end foo2; -- ERRONEOUS - COMPILES WITH WARNING
procedure foo3(o: out Integer) is
begin
o := 3;
end foo3;
procedure foo4(i: in Integer) is
begin
foo3(i); -- COMPILATION ERROR
end foo4;
procedure foo5(o: out Integer) is
begin
put(o); -- ERRONEOUS - COMPILES WITH WARNING
end foo5;
Functions
- Procedure = void method
- Function = non-void method
- ie method with a non-void type
- Procedures calls are statements
- Function calls represent values
Example Functions
- Example: Use functions to calculate sum of 1..n and sum of squares of 1..n
procedure demo is
function sumInts(n: in Natural) return Natural is
s: Natural;
begin
s := 0;
for i in 1 .. n loop
s := s + n;
end loop;
return s;
end sumInts;
function sumSquares(n: in Natural) return Natural is
ssq: Natural;
begin
ssq := 0;
for i in 1 .. n loop
ssq := ssq + n**2;
end loop;
return ssq;
end sumInts;
n, sumUpToN: Natural;
begin
get(n);
sumUpToN := sumInts(n); -- Call represents a value
put(sumUpToN);
put(sumSquares(n)); -- Call represents a value
end demo;
Restrictions on Functions
- Parameters must be IN mode
- Why: to avoid side effects
- Return statement required
- Type of returned value must match declaration
- Functions can NOT be used as statements, unlike this legal Java
public class Func {
public static int foo(){ // Non-void return type
System.out.println(111);
return 3;
}
public static void main(String[] args) {
foo(); // function used as statement
// return value ignored
System.out.println(22);
}
}
Terminology: Procedures, functions, methods, routines
- Remember: Procedure = void method
- Remember: Procedure = non-void method (ie method with a non-void return type)
- We can use the term routine (or subroutine) to refer to a procedure or a function
- Sometimes we informally use procedure when we mean procedure and/or function
Question: Can we call multiple functions
- Question: Can you have a function call as an argument to a function call?
- Answer: Sure
- Example: put(reverse(toUpper(name)))
- compare to java: System.out.print(name.toUpper().reverse())
Side Effects
Looking Ahead: Arrays as Parameters
- If a routine requires an array as a parameter
- then the array must have a named type
- Example:
procedure demo is
-- Declare a new type
type IntArray is array (1 .. 10) of Natural;
procedure p(a: IntArray) is ...
begin
...
end p;
-- Declare a variable
myArray: IntArray;
begin -- demo
p(myArray);
...