The Term of Function
The most important technological breakthrough in computer engineering is
the possibility of creation and storage of separate code fragments
that describe the rules of data processing for solving a problem or a small task. Such a possibility exists in MQL4, too.
Function is a named, specific part of a program that describes the method of data conversion.
Speaking about functions, we will consider two aspects: function description and function call.
Function description is a specific named part of a program intended for execution.
Function call (function reference) is a record, execution of which results in execution of a function.
In our everyday life, we can find many analogues of the function.
Take, for example, the braking system of a car. The actuating mechanism that properly performs braking, as well as the idea implemented by the engineer, is the analogue of a function, whereas brake pedal is the analogue of function call. The driver presses the pedal down, and the actuating mechanisms
perform some actions and - stop the car.
Similarly, if a function call occurs in a program, then the function of the same name will be called and executed, i.e., a certain sequence of calculations or other actions will be performed (for example, displaying a message or opening an order, etc.). The general sense of a function is in taking a logically completed part of the code outside the basic text of the program, whereas only the call for this part of the code remains inside the basic text of the program. Such program construction has some incontestable advantages:
- first, the program text composed in such a manner is read much easier;
- second, one can easily see and, if necessary, modify the text of a function without making any changes in the basic code of the program;
- third, a function can be composed as a single file and use it in other programs, which will release the programmer from the necessity to insert the same fragments of the code in each newly created program.
We can say that the most part of the code in programs composed using MQL4 is written in form of functions. This approach became widespread and is a standard now.
Composition of a Function
Thus, a function can be described and called. Let's consider an example. Suppose we have a small program (Fig. 18) that finds the length of hypotenuse using two other sides of the right triangle and Pythagorean theorem.
||In this program, all calculations are located together, the operators are executed one by one in the order, in which they occur in the program
(from the top down).
Fig. 18. The code of single program pifagor.mq4.
||Problem 8. Compose a part of the given program code as a function.
It would be reasonable to make a function using the two lines that find the search value. The same program using a function is shown in Fig. 19.
||In this program, a part of calculations is composed as a function. The basic code contains a user-defined function call. The description of the user-defined function is located outside (after) the basic code.
Fig. 19. The code of a program that contains the description of and the call for user-defined function gipo.mq4.
Both versions of the program will give the same result.
However, the code is composed as a single module in the first version (Fig. 18), whereas in the second version (Fig. 19) a part of calculations is executed in a function called from the basic text. Upon completion of the calculations separated into the function, the calculations in the main code will be continued.
To have the function executed, we have to call it
(refer to it). This is why the function is practically represented in two parts: the code itself composing the function (function description)
and the function call used to launch the function (referring to the function). If you don't call the function, it will not be executed. At the same time, if you call a nonexistent function, this will result in nothing (MetaEditior will give an error message if you try to compile such a program in MQL4).
The description of a function consists of two basic parts - function header and function body.
The header of a function consists of the type of the return value, function name and the list of
formal parameters. The list of formal parameters are enclosed in parentheses and placed after the function name. The type of the return value can be one of the types we already know: int, double, bool, color, datetime, or string. If the function does not return any value, its type can be denoted as
void ("without contents, empty") or as any other type.
The body of a function is enclosed in braces. The function body may contain simple and/or compound operators, as well as calls for other functions. The value returned by the function is given in the parentheses of
operator return(). The type of the value returned using operator
return(), must match with the function type specified in the function header.
The description of the function is ended with a closing brace.
Fig. 20. Function description.
||The function description must be located separately in the program, outside any other functions (i.e., not inside of a function, but outside it).
Function call represents the function name and the list of transferred parameters. The list of transferred parameters is enclosed in parentheses. The function call can be represented as a separate operator or as a part of an operator.
Fig. 21. Function call (reference to a function).
||Any function call is always specified within another function (i.e., not outside all other functions, but inside one of them).
There are three types of functions - special functions, standard (built-in, predefined) functions, and user-defined functions.
In MQL4, there are 3 special functions in total. They have predefined names: init(), start(), and deinit() that may not be used in the names of any other functions. The detailed consideration of special functions is given in chapter Special Functions. We only say here that the basic code of a program is located inside these functions (Fig. 18, 19).
The special feature of special functions is the fact that they are called for execution by the client terminal. Although special functions have all properties of functions in general, they are not usually called from the program if this program is coded properly.
MQL4 has a number of useful functions that don't need being described when coding a program. For example, computing square roots, printing messages in the system journal or on the screen - all these and many other standard functions
are executed according to the predefined algorithm.
The user needn't to learn the contents of these functions. He or she can just be sure that all standard functions are developed by professionals properly and according to the best possible algorithm.
The special feature of standard functions is that they are not described in the text of the program. The standard functions are called in the program in the same manner as when using any other functions (it's a common practice).
In our example (Fig. 18, 19), two standard functions are used:
MathSqrt() and Alert(). The former one is intended for computing of square roots, whereas the latter one is for messaging a certain text enclosed in parentheses to the screen. The properties of standard functions are considered in more details in section Standard Functions.
Here we will note that these records represent standard function calls, whereas no descriptions of these functions can be found in the program. Standard functions can also be named built-in, or predefined functions. You may use any of these terms.
In some cases, programmers create and use their own functions. We call these functions user-defined functions. User-defined functions are utilized in programs with both function descriptions and function calls.
Table 1. Function description and function call used in programs for functions of different types.
||Not applicable (*)
(*) Although special functions can be technically called from a program, it is not recommended to do so.
Properties of Functions
The main property of all functions is that the called functions are executed. Functions are executed according to their codes.
Passed Parameters and Return Value
As to information received and returned, a function is like a standard calculator. You can type (using its keyboard) a certain expression that consists of several values entered one by one, and you will obtain one value as an answer. A function can get and process one or several parameters from the program that has called this function for execution, and the function will finish its operation by returning (transmitting, giving) one parameter as an answer to this program.
The passed parameters are specified by enclosing in parentheses after the name of the function to be called. The passed parameters are usually separated by commas. The number of parameters passed to the function must not exceed 64. The function may also omit using the passed parameters. In this case, an empty list of parameters is specified, i.e., you just put an opening parenthesis and a closing parenthesis directly after the function name.
The number, types and order of the passed parameters in the function call must match with those of formal parameters specified in the function description
(the call for a function that has default parameters is an exemption - see Function Call and Function Description and the Operator "return").
If they don't match, MetaEditor will give you an error message. Constants, variable, expressions and arrays may be used as passed parameters.
The return value is specified in the parentheses of the operator return() (see Function Description and the Operator "return").
The type of the value returned using operator return() must match with the type of the function given in the function header. It is also possible that a function does not return any value. In this case, nothing is specified in the parentheses of the operator
In our example, the passed parameters are variables A and B (Fig. 21), whereas the return value is variable c (Fig. 20). The requirement of matching the types of passed and formal parameters can be seen in Fig. 22.
||The number, types and order of the passed parameters in the function
call must match with those of formal parameters specified in the
function description. Only variables can be used in the header of the function description as formal parameters.
Fig. 22. Match in the number, types and order of passed and formal parameters. Only variables are used as passed parameters.
||Only variables, expressions and constants can be used as passed parameters.
Fig. 23. Match in the number, types and order of passed and formal parameters. A constant, an expression, and variables of the corresponding type are used as passed parameters.
A high point of functions is the use of formal parameters.
Formal parameters are a list of variables specified in the header of the function description.
We mentioned before that one function could be used in several programs. However, different programs use different names for the variables. If functions required strict matching in the names of variables (and, correspondingly, in their value), it wouldn't be convenient for programmers. Indeed, you would then have to compose each newly developed program in the names of variables that had already been used in your functions before. However, fortunately, the variables used inside functions have no relations to the variables used in a program.
Let's refer to Fig. 20 and 21 once again. It should be noted that the names of the passed parameters (A and B are given in the parentheses of the function call) do not match with the names of the parameters (a and b) specified in the function description. We noticed in the section Constants and Variables that MQL4 is case-sensitive. Thus, the names A and a, B and b considered here are different names of variables. However, there is no error in this code.
The variables (formal parameters) used in the function description are not related to the variables used in the basic code of the program. They are just different variables. Only variables, but not constants, can be specified in the function header as formal parameters.
How It Works
- In the program, there occurs a function call, variables A and B being specified in its parentheses.
- The program calls the function of the same name, which has formal parameters
a and b specified in its header.
- The value of variable A is assigned to variable a.
- The value of variable B is assigned to variable b.
- The executable function performs calculations using the values of variables a and b.
It is allowed to use any names of formal parameters (that don't coincide with the names of the variables used in the program). In this example, we used the identifiers of formal parameters a and b. However, we could use any others, for example, m and n, or Kat_1 and Kat_2. Of course, when writing a program, you should specify in the function body the calculations that use the names of variables that are given in the header. Since we have given a and b in the header, so we have to use in the function a and b, not m and n.
In a function, the calculations are made that involve formal parameters a and b, but not variables A and B. In a function, any allowed actions may be perform on formal parameters a and b (including the changes in the values of these variables). This does not have any effect on variables A and B.
The return value calculated in the function is given in the parentheses of the operator return(). The value of a variable, the result of an expression, or a constant can be used as return value. In our case, this is the value of local variable c (local variable is a variable declared within a function; if you exit the function, the values of all local variables will be lost; we will consider more details about local variables in the section Types of Variables). The function returns into the program the value of local variable c (Fig. 19). This means that this value will now be assigned to variable C.
Further calculations in the program, if any, can be performed with the variables declared within the calling function.
In our case, calling function is special function start() (it contains the line for calling the user-defined function), whereas the variables declared within the calling function are A, B, and C.
Thus, in the function the calculations are performed using formal parameters, which allows us to create functions using arbitrary names of variables, irrespective of the names of values actually used in the program.
Example: Standard Functions in a Program
First of all, let's consider the behavior of the program shown in Fig. 18. We should note that the entire code of the program is located inside the special function
start(). At this training phase, we won't pay special attention to this
(special functions and their properties are considered in more details in the section Special Functions).
Let's follow the execution of the program starting with the assignment operator:
int A = 3;
1. The right part of the assignment operator contains the specified constant, its value is 3.
2. The value of 3 (the value of the right part) is assigned to variable A (that locates to the left of the equality sign in the assignment operator).
The control is given to the next line:
int B = 4;
3. The right part of the assignment operator contains the specified constant, its value is 4.
4. The value of 4 is assigned to variable B.
The program goes to execution of the next line:
int C_2 = A*A + B*B; um of the squares of catheti
5. Calculation of the right part of the assignment operator. The result of the calculations is the value of 25 (the details of how a program refers to variables to take their values are considered in the section Constants and Variables, so we aren't particularizing this point here now).
6. Assignment of the value 25 to variable C_2.
The next line represents an assignment operator, the right part of which contains a call for the standard function:
int C = MathSqrt( C_2);
The program seeks to execute the assignment operator. For this purpose, it executes calculations to the right of the equality sign first.
7. The program calls for execution the standard function MathSqrt() (that calculates square roots). The value of variable C_2 (in our case, this value is equal to 25) will be used as the passed parameter. Note that there is no description of this standard function anywhere in the program. The descriptions of standard functions must not be located in programs. In the text of a program, you can easily distinguish the standard function call by its appearance: they are highlighted in MetaEditor with dark blue (programmer may choose colors voluntarily).
8. The calculations are made in the standard function MathSqrt().
9. The standard function MathSqrt() has completed its calculations. It returns the obtained value. In our case, it is the value of 5 (the square root of 25).
The value returned by the function is now the content of the record:
This record can be considered as a special, complex variable,
a kind of a thing, inside which the calculations are performed. After these calculations have been completed, the thing takes a value. The determining is here the fact that the value returned by the function can be assigned to another variable or considered somehow in any other calculations.
10. In this case, our value is the value of the right part of the assignment operator. On continuing execution of the assignment operator, the program will assign the value of 5 to variable C.
11. The next line contains operator that references to the standard function Alert() (function call).
Alert("Hypotenuse = ", C);
The standard function Alert() opens a dialog box where
the values of the passed parameters are displayed. In this case, the function has taken two values as the passed parameters:
- the value of string constant: Hypotenuse =
- the value of integer variable C: 5
It was noted above that not all functions must return the value (that is the result of the function execution). The standard function Alert() does not return any value, since it has another task - it must display the text on the screen, in a special window.
As a result of execution of the standard function Alert(), in the window of this function the following line will appear:
12. The last operator in this program completes the work of the special function start().
The work of the program is finished at this point.
A question may arise: How can we know what function will return the value, and what not? The answer to this question is obvious: In order to find the detailed descriptions of built-in functions, you should read the
reference documentation in MQL4.community, the website launched by MetaQuotes Software Corp.,
or the Help File of MetaEditor. The properties of a user-defined function are specified in its description. Whether a user-defined function returns the value or not, depends on its algorithm (the decision is made by the programmer at the stage of writing the program code of the function).
Example: User-Defined Function in a Program
Let's consider how the same calculations are made in the program containing a user-defined function (Fig. 19). A certain part of the code
that could previously to be found in the special function start(), is unavailable now. It is replaced with the call for the user-defined function. However, the special function start() is followed by the description of the user-defined function.
The first two lines, in which integer variables A and B take numeric values, remain the same. Consequently, nothing changes in their execution:
int A = 3;
int B = 4;
In the third line we have the assignment operator. Its right part contains the call for the user-defined function:
int C = Gipo(A,B);
6. On executing this operator, the program will first of all call the user-defined function.
Note: The description of the user-defined function must be present in your program and placed immediately after the brace that closes the special function start() (i.e., outside the special function).
In referring to the user-defined function, the program will perform the following:
6.1. Calling for variable A in order to get its value (in our case, 3)
6.2. Calling for variable B in order to get its value (in our case, 4)
Note: As soon as the program starts to call the user-defined function (the function is user-defined, in our specific case; this rule applies to all functions), the program gets just a copy of the values of variables used as passed parameters, whereas the values of these variables themselves (in this case, A and B) are not supposed to change due to application of the user-defined function, nor they really change.
7. The control is passed to the user-defined function.
During the whole time of execution of the user-defined function (no matter how long it takes), the values of variables in the calling program will not get lost, but will be stored.
The first line in the description of the user-defined function is its header:
int Gipo(int a, int b)
On executing the user-defined function, the program will do the following:
7.1. The value of 3 (the first value in the list of passed parameters) will be assigned to variable a (the first variable in the list of formal parameters).
7.2. The value of 4 (the second value in the list of passed parameters) will be assigned to variable b (the second variable in the list of formal parameters).
Then the control will be passed to the function body for it to execute its algorithm.
The first operator in the function body is:
int c2 = a*a + b*b; um of the squares of catheti
7.3. On executing this operator, the program calculates the value in the right part of the assignment operator, and after that it will assign the obtained value (in our case, 3*3 +
4*4 = 25) to variable c2.
The next operator:
int c = MathSqrt(c2);
7.4. Here we find the square root of the value of variable c2.
The order of operations is the same as in the previous example. The description of standard function is not used either. The execution of the assignment operator will result in assigning the value of 5 to variable c.
7.5. In the next line, we have operator:
On executing this operator, the program will return (to the call site of the user-defined function) the value enclosed in the parentheses of this operator. In our case, it is the value of variable c, i.e. 5.
At this point, the execution of the user-defined function is over, the control is given to the call site.
8. Recall that the user-defined function was called from the operator
int C = Gipo(A,B);
The record (the user-defined function call)
at the stage of returning the value, takes the value calculated in the function (in our case, it is the value of 5).
On completing the execution of the assignment operator, the program will assign the value of 5 to the variable C.
9. The next operator,
Alert("Hypotenuse = ", C);
will be executed in the same way as in the previous example, namely: in a special window, there will a message appear:
10. The last operator in this program,
completes the work of the special function start(),and simultaneously completes the work of the entire program (the properties of special functions are considered in more details in the section Special Functions).
Let's consider some implementation versions of the above user-defined function. It is easy to verify that programming with user-defined functions has some incontestable advantages.
Previously Considered Implementation of User-Defined Function Gipo()
In this function, the formal parameters "resemble" the variables used in the basic program. However, this is just a formal similarity, because A and a are the different names of variables.
int Gipo(int a, int b)
int c2 = a*a + b*b; um of the squares of catheti
int c = MathSqrt(c2);
Implementation of User-Defined Function Gipo(): Version 2
In this case, the names of formal parameters do not "resemble" the names of variables used in the basic program. However, this doesn't prevent us from using this function in the program.
int Gipo(int alpha, int betta)
int SQRT = alpha*alpha + betta*betta; um of the squares of catheti
int GIP = MathSqrt(SQRT);
Implementation of User-Defined Function Gipo(): Version 3
In this example, the variable alpha is reused in the program and changes its value twice. This fact has no effect on the actual variables specified in the function calls of the main program.
int Gipo(int alpha, int betta)
alpha= alpha*alpha + betta*betta; um of the squares of catheti
Implementation of User-Defined Function Gipo(): Version 4
In this user-defined function, all calculations are collected in one operator. The return value is calculated directly in the parentheses of the operator
return(). The subduplicate is calculated directly in the location where the passed parameter must be specified in the standard function MathSqrt().This solution may seem to be strange or wrong at the beginning. However, there is no error in this implementation of the user-defined function. The number of operators used in the function is smaller than in other implementations, so the code turns out to be more compact.
int Gipo(int a, int b)
return(MathSqrt(a*a + b*b));
Thus, the application of user-defined functions has some incontestable advantages in the programming practice:
- the names of variables in the basic text of the program have no relations to the names of formal parameters in a user-defined function;
- user-defined functions can be reused in different programs, there is no need to change the code of a user-defined function;
- libraries can be created, if necessary.
These very useful properties of functions allow to create really large programs in a corporation, for example. Several programmers can be involved in this process simultaneously, and they a released from the necessity to agree about the names of variables they use. The only thing to be agreed is
the order of variables in the header and in the function call.