|
Functions and Procedures Arguments |
|
Introduction to Arguments
|
|
An argument is a variable that is given to a procedure or a function that needs it to perform the intended assignment. Giving the arguments to a procedure or function is referred to as passing them.
To declare or define a procedure or a function that takes one argument, type the name of the argument between parentheses that follow the name of the procedure or function. Between these parentheses, the name of the argument must be followed by its type as if it were regularly declared. Here is an example: |
Procedure ShowMe(Length : Double);
To declare a procedure or a function that takes more than one argument, type each argument and its data type followed by a semi-colon except for the last argument. Here is an example:
|
Procedure ProcessRectangle(Length : Double; Width : Double);
If the procedure or function takes two or more arguments that are of the same type, you can type each argument of the same type, separating them with a comma. Here is an example: |
procedure MbrRegist(Gender, Category: Char; Fee: Double);
begin
end;
In the body of the procedure or function, define the behavior of the assignment. |
Procedure ProcessRectangle(Length : Double; Width : Double);
var
Perimeter : Double;
Area : Double;
begin
Perimeter := 2 * (Length + Width);
Area := Length * Width;
writeln('The perimeter of the rectangle is ', Perimeter);
writeln('The area of the rectangle is ', Area);
end;
When we reviewed earlier how to call a simple procedure or a function, we saw that you can just type the name of the procedure or function where you need it. This rule is not strictly applied when the procedure or function takes at least one argument.
When a procedure or function takes at least one argument, the argument is required when calling the procedure or function: if you do not supply a value for the argument, the program would not compile and you would receive an error. For example, the following program will not compile: |
program Project1;
{$APPTYPE CONSOLE}
Procedure StopHere(GoodBye: string);
begin
write(GoodBye);
readln;
end;
begin
StopHere;
end.
This program does not work because the StopHere procedure takes an argument but when calling it, the argument is not passed as required. When calling a procedure or function that takes an argument, provide a value that will be used by the procedure or function between its parentheses. The argument can be passed as a constant value. Here is an example: |
program Project1;
{$APPTYPE CONSOLE}
Procedure StopHere(GoodBye: string);
begin
write(GoodBye);
readln;
end;
begin
StopHere('Press any key to continue');
end.
You can also pass the argument using a declared and possibly initialized variable. Here is an example: |
program Project1;
{$APPTYPE CONSOLE}
Procedure StopHere(GoodBye: string);
begin
write(GoodBye);
readln;
end;
Function TwoTimes(Nbr: Double) : Double;
begin
Result := Nbr * 2;
end;
var
Number: Double;
Multiplied: Double;
begin
Number := 252.88;
Multiplied := TwoTimes(Number);
Writeln(Multiplied:2:2);
StopHere('Press any key to continue');
end.
|
|
4.5.2 Arguments by Value
There are two ways an argument is passed to a procedure or a function: by value or by reference. The most usual way of passing arguments to a procedure or a function is by value. That is the way we have used arguments on functions so far.
We saw earlier that, to use a function inside of another function, that is, to call a function from another function, specify the name of the function and its list of arguments, if any, inside of parentheses. Consider the following formula to calculate the tax amount applied to an item in a department store;
The formula of calculating the final price of an item is:
Final Price = Item Price + Tax Amount
Here is an example of passing arguments by value, the same way we have done so far: |
program Project1;
{$APPTYPE CONSOLE}
function PurchasePrice(ItemPrice, TaxRate: double) : double;
var
Price: Double;
begin
Price := ItemPrice + (ItemPrice * TaxRate / 100);
Result := Price;
end;
var
ItemPrice, TaxRate: Double;
begin
Write('Enter the price of the item: ');
Readln(ItemPrice);
Write('Enter the tax rate: ');
Readln(TaxRate);
Writeln;
Writeln('The final price is: $', PurchasePrice(ItemPrice, TaxRate):2:2);
write('Press any key to continue');
readln;
end.
Here is an example of running the program: |
Enter the price of the item: 255.95
Enter the tax rate: 5.75
The final price is: $270.67
Press any key to continue
When you declare a variable in a program, the compiler reserves an amount of space for that variable. If you need to use that variable somewhere in your program, you call it and make use of its value. There are two major issues related to a variable: its value and its location in memory. Imagine you declare a variable named Variable1:
The location of a variable in memory is referred to as its address.
If you supply the argument using its name, the compiler only makes a copy of the argument’s value and gives it to the calling function. Although the calling function receives the argument’s value and can use it in any way, it cannot (permanently) alter it. Object Pascal allows a calling function to modify the value of a passed argument if you find it necessary. If you want the calling function to modify the value of a supplied argument and return the modified value, you should pass the argument as reference.
To pass an argument as reference, when declaring the function, precede the name of the argument with the var keyword. You can pass one or more arguments as reference in the program or pass all arguments as reference. The decision as to which
argument(s) should be passed by value or by reference is based on whether or not you want the called function to modify the argument and permanently change its value.
Here are examples of passing some arguments by reference: |
procedure Area(var Side: Double); // The argument is passed by reference
function Decision(var Answer: Char; Age: Integer) : Boolean; // One argument is passed by reference
// All arguments are passed by reference
function Purchase(var DiscountPrice, NewDiscount: Single; var Commission: Char) : Single;
You add the var keyword when declaring a function and when defining it. When calling the procedure or function, supply only the name of the referenced
argument(s). The above would be called with: |
Area(S);
Decision(Ans, A);
Purchase(DiscPrice, NewDisc, Coms);
You will usually need to know what happens to the value passed to a calling function because the rest of the program may depend on it. Imagine that you write a function that calculates employees weekly salary provided the total weekly hours and hourly rate. The starting program would be as follows: |
program Project1;
{$APPTYPE CONSOLE}
procedure Earnings(ThisWeek, Salary: Double);
begin
Writeln('In the Earnings() function,');
Writeln('Weekly Hours = ', ThisWeek:2:2);
Writeln('Salary = ', Salary:2:2);
Writeln('Weekly Salary = ', (ThisWeek * Salary):2:2);
end;
var
Hours, Rate, Wage: Double;
begin
Write('Enter the total Weekly hours: ');
Readln(Hours);
Write('Enter the employee''s hourly rate: ');
Readln(Rate);
Writeln;
Writeln('In the main() function,');
Writeln('Weekly Hours = ', Hours:2:2);
Writeln('Salary = ', Rate:2:2);
Writeln('Weekly Salary: ', (Hours * Rate):2:2);
Writeln;
Writeln('Calling the Earnings() function');
Earnings(Hours, Rate);
Writeln('After calling the Earnings() function, ');
Writeln('in the main() function,');
Writeln;
Writeln('Weekly Hours = ', Hours:2:2);
Writeln('Salary = ', Rate:2:2);
Writeln('Weekly Salary: ', (Hours * Rate):2:2);
Writeln;
write('Press any key to continue');
readln;
end.
If you test the program by typing 32 for the weekly hours and 6.45 for the salary, you would notice the weekly values are the same: |
Enter the total Weekly hours: 32
Enter the employee's hourly rate: 6.45
In the main() function,
Weekly Hours = 32.00
Salary = 6.45
Weekly Salary: 206.40
Calling the Earnings() function
In the Earnings() function,
Weekly Hours = 32.00
Salary = 6.45
Weekly Salary = 206.40
After calling the Earnings() function,
in the main() function,
Weekly Hours = 32.00
Salary = 6.45
Weekly Salary: 206.40
Press any key to continue
Imagine that the employee claims to have worked 42 hours instead of the passed weekly hours. You could create the following function to find out. |
procedure Earnings(ThisWeek, Salary: Double);
begin
ThisWeek := 42;
Writeln('In the Earnings() function,');
Writeln('Weekly Hours = ', ThisWeek:2:2);
Writeln('Salary = ', Salary:2:2);
Writeln('Weekly Salary = ', (ThisWeek * Salary):2:2);
end;
If you test the program with a weekly hours value of 35.50 and a salary of 8.50, you would notice that the weekly salary is different inside of the Earnings() function but is kept the same in
main section of the program, before and after the Earnings() function: |
Enter the total Weekly hours: 35.50
Enter the employee's hourly rate: 8.50
In the main() function,
Weekly Hours = 35.50
Salary = 8.50
Weekly Salary: 301.75
Calling the Earnings() function
In the Earnings() function,
Weekly Hours = 42.00
Salary = 8.50
Weekly Salary = 357.00
After calling the Earnings() function,
in the main() function,
Weekly Hours = 35.50
Salary = 8.50
Weekly Salary: 301.75
Press any key to continue
Notice that the Weekly salary is the same before and after calling the Eranings procedure. If you want a calling function to modify the value of an argument, you should supply its reference and not its value. You could change the function as follows: |
procedure Earnings(var ThisWeek: Double; Salary: Double);
begin
ThisWeek := 42;
Writeln('In the Earnings() function,');
Writeln('Weekly Hours = ', ThisWeek:2:2);
Writeln('Salary = ', Salary:2:2);
Writeln('Weekly Salary = ', (ThisWeek * Salary):2:2);
end;
Here is a new test of the program: |
Enter the total Weekly hours: 35.50
Enter the employee's hourly rate: 8.50
In the main() function,
Weekly Hours = 35.50
Salary = 8.50
Weekly Salary: 301.75
Calling the Earnings() function
In the Earnings() function,
Weekly Hours = 42.00
Salary = 8.50
Weekly Salary = 357.00
After calling the Earnings() function,
in the main() function,
Weekly Hours = 42.00
Salary = 8.50
Weekly Salary: 357.00
Press any key to continue
Notice that, this time, once the Earnings procedure has been called, the weekly salary, whose calculation involves the ThisWeek argument passed as reference, has a changed value. |
We mentioned earlier that, whenever a function takes
an argument, that argument is required. If the calling function does not
provide the (required) argument, the compiler would throw an error.
Imagine you write a function that will be used to calculate the final
price of an item after discount. The function would need the discount rate
in order to perform the calculation. Such a function could look like this: |
function CalculateNetPrice(DiscountRate: double) : double;
var
OrigPrice: Double;
begin
Write('Please enter the original price: ');
Readln(OrigPrice);
Result := OrigPrice - (OrigPrice * DiscountRate / 100);
end;
Since this function expects an argument, if you do not supply it, the following program would not compile: |
program Project1;
{$APPTYPE CONSOLE}
function CalculateNetPrice(DiscountRate: double) : double;
var
OrigPrice: Double;
begin
Write('Please enter the original price: ');
Readln(OrigPrice);
Result := OrigPrice - (OrigPrice * DiscountRate / 100);
end;
var
FinalPrice, Discount: Double;
begin
Discount := 15;
FinalPrice := CalculateNetPrice(Discount);
Writeln('After applying the discount');
Writeln('Final Price = ', FinalPrice:2:2);
Writeln;
write('Press any key to continue');
readln;
end.
Here is an example of running the program: |
Please enter the original price: 250.95
After applying the discount
Final Price = 213.31
Press any key to continue
Most of the time, a function such as ours would use the same discount rate over and over again. Therefore, instead of supplying an argument all the time, Object Pascal allows you to define an argument whose value would be used whenever the function is not provided with the argument.
To give a default value to an argument, when declaring the function, type the name of the argument followed by the colon operator “:”, followed by the argument’s data type, followed by the equality operator, and followed by the desired default value. The
CalculateNetPrice() function, with a default value, could be defined as follows: |
function CalculateNetPrice(DiscountRate: double = 25) : double;
var
OrigPrice: Double;
begin
Write('Please enter the original price: ');
Readln(OrigPrice);
Result := OrigPrice - (OrigPrice * DiscountRate / 100);
end;
When calling the procedure, you can omit passing a value for the argument. If you do not pass it, the default value would be used. Therefore, you can just call the procedure as follows: |
begin
Discount := 15;
FinalPrice := CalculateNetPrice;
Writeln('After applying the discount');
Writeln('Final Price = ', FinalPrice:2:2);
Writeln;
write('Press any key to continue');
readln;
end.
If a procedure or a function takes more than one argument, you can provide a default argument for each and select which ones would have default values. If you want all arguments to have default values, when defining the procedure or function, type each the = operator for each argument. Here is an example: |
program Project1;
{$APPTYPE CONSOLE}
function CalculateNetPrice(Tax: Double = 5.75; Discount: Double = 25;
OrigPrice: double = 245.55) : double;
var
DiscountValue, TaxValue, NetPrice: double;
begin
DiscountValue := OrigPrice * Discount / 100;
TaxValue := Tax / 100;
NetPrice := OrigPrice - DiscountValue + TaxValue;
Writeln('Original Price: $', OrigPrice:6:2);
Writeln('Discount Rate: ', Discount:6:2, '%');
Writeln('Tax Amount: $', Tax:6:2);
Result := NetPrice;
end;
var
FinalPrice, Discount: Double;
begin
Discount := 15;
FinalPrice := CalculateNetPrice;
Writeln;
Writeln('After applying the discount');
Writeln('Final Price = $', FinalPrice:2:2);
Writeln;
write('Press any key to continue');
readln;
end.
Here is the result produced: |
Original Price: $245.55
Discount Rate: 25.00%
Tax Amount: $ 5.75
After applying the discount
Final Price = $184.22
Press any key to continue
If a function takes more than one argument and you would like to provide default values for those parameters, the order of appearance of the arguments is very important.
1/ If a function takes two arguments, you can declare it with default values. We already know how to do that. If you want to provide a default value for only one of the arguments, the argument that would have a default value must be the second in the list. Here is an example: |
function CalculateNetPrice(Tax: Double; Discount: Double = 25) : Double;
When calling such a function, if you supply only one argument, the compiler would assign its value to the first parameter in the list and ignore assigning a value to the second: |
program Project1;
{$APPTYPE CONSOLE}
function CalculateNetPrice(Tax: Double; Discount: Double = 25) : Double;
var
OrigPrice, DiscountValue, TaxValue, NetPrice: Double;
begin
Write('Enter the original price of the item: ');
Readln(OrigPrice);
DiscountValue := OrigPrice * Discount / 100;
TaxValue := Tax / 100;
NetPrice := OrigPrice - DiscountValue + TaxValue;
Result := NetPrice;
end;
var
FinalPrice, TaxRate: Double;
begin
TaxRate := 5.50; // = 5.50%
FinalPrice := CalculateNetPrice(TaxRate);
Writeln('After applying the discount');
Writeln('Final Price = $', FinalPrice:5:2);
Writeln;
write('Press any key to continue');
readln;
end.
Here is an example of running the program: |
Enter the original price of the item: 250.50
After applying the discount
Final Price = $187.93
Press any key to continue
If you define the function and assign a default value to the first argument, if you provide only one argument when calling the function, you would receive an error.
2/ If the function receives more than two arguments and you would like only some of those arguments to have default values, the arguments that would have default values must be at the end of the list. Regardless of how many arguments would or would not have default values, start the list of arguments without those that would not use default values. |
A program can involve a great deal of names that represent variables, procedures, and functions of various kinds. The compiler does not allow two entities to share a name. For example, two variables must not have the name in the same function. Although two functions should have unique names in the same program, Object Pascal allows you to use the same name for different functions of the same program following certain rules. The ability to have various functions with the same name in the same program is called function overloading.
To implement function overloading, make sure that each one of the procedures or functions has a different number or different types of arguments. When declaring or defining the procedure or function, type the overload keyword at the end of its declaration. When calling the procedure or function, the compiler will locate the appropriate procedure or function based on the number of arguments you provide. For example, you can create a function called Area() but define it to calculate the areas of different shapes: |
program Project1;
{$APPTYPE CONSOLE}
// Area of a square
function Area(Side: Single) : Single; overload;
begin
Result := Side * Side;
end;
// Area of a rectangle
function Area(Length: Single; Width: Single) : Single; overload;
begin
Result := Length * Width;
end;
begin
Writeln('The area of the square is ', Area(22.52):5:3);
Writeln('The area of the rectangle is ', Area(18.04, 12.64):5:3);
Writeln;
write('Press any key to continue');
Readln;
end.
Here is the result of running the program: |
The area of the square is 507.150
The area of the rectangle is 228.026
Press any key to continue
To calculate the moment of inertia with regard to the X axis, change the file as follows: |
When a routine receives an argument, it performs one of two actions with regards to the value of the argument; it may modify the value itself or only use the argument to modify another argument or another of its own local variables. Consider the following Twice function: |
program Project1;
{$APPTYPE CONSOLE}
function Twice(Nbr1: Double) : Double;
begin
Result := Nbr1 * 2;
end;
var
Number1: Double;
Total: Double;
begin
Number1 := 1450.68;
Total := Twice(Number1);
Writeln(Number1:6:2, ' * 2 = ', Total:5:2);
Writeln;
Write('Press any key to continue...');
readln;
end.
If you know that the routine is not supposed to alter the value of an argument, you should let the compiler know. This is a safeguard that serves at least two purposes. First, the compiler will make sure that the argument supplied stays intact; if the function tries to modify the argument, the compiler would throw an error, letting you know that an undesired operation took place. Second, this speeds up execution.
To let the compiler know that the value of an argument must stay constant, type the const keyword on the left of the name of the argument. For example, the above Twice function does not alter the value of its argument. Therefore, the argument can be passed as constant and this would be done as follows: |
function Twice(const Nbr1: Double) : Double;
begin
Result := Nbr1 * 2;
end;
1450.68 * 2 = 2901.36
Press any key to continue...
In the same way, you can pass as many constant arguments as you judge necessary for a routine. You can make just one or more arguments constants, and there is no order on which arguments can be made constant. Here is another function that takes two constant arguments: |
program Project1;
{$APPTYPE CONSOLE}
function Twice(const Nbr1: Double) : Double;
begin
Result := Nbr1 * 2;
end;
function AddTwoNumbers(const Nbr1: Double; const Nbr2: Double) : Double;
begin
Result := Nbr1 + Nbr2;
end;
var
Number1, Number2: Double;
Total: Double;
begin
Number1 := 1450.68;
Number2 := -360.55;
Total := Twice(Number1);
Writeln(Number1:6:2, ' * 2 = ', Total:5:2);
Total := AddTwoNumbers(Number1, Number2);
Writeln(Number1:6:2, ' + ', Number2:6:2, ' = ', Total:5:2);
Writeln;
Write('Press any key to continue...');
readln;
end.
1450.68 * 2 = 2901.36
1450.68 + -360.55 = 1090.13
Press any key to continue...