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
Arguments by Reference
|
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.
|
Default Arguments
|
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. |
Function Overloading
|
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:
|
Constant Arguments
|
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;
This would produce:
|
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.
This would produce:
|
1450.68 * 2 = 2901.36 1450.68 + -360.55 = 1090.13 Press any key to continue...
No comments:
Post a Comment