|
Now we will introduce Error handling which is one of the basic principles of any programming language. A good error handling mechanism allows to avoid strange behavior when there are errors during execution of code.
Let's suppose to have a line of code like the following :
I = 10 / A
If the variable "A" has value of zero, the division will produce an error. In fact is not possible to divide any number by zero. The command interpreter, if there was no Error Handling, would terminate code execution without producing the desired result.
The Error Handling is done using the following instructions:
|
Goto Label
|
If a line of code following this instruction will generate an error, then the command interpreter will transfer the control to the line following the "Label". This instruction has the same effect as the "GoTo" command, with the only difference that the transfer of control does happen only in case of error.
|
|
Error Next
|
If instead of "Label" there is the keyword "Next" the error will be ignored, and the execution will continue with the following line after the one where the error was generated. In case there is an error on the first line of instructions like "IF", "FOR", "DO UNTIL", "SELECT CASE", the control will be transferred to the line following the block of instructions.
|
|
Resume
|
This instruction is used alongside the Error Label. It is used to transfer the control flow to the line subsequent to the one which generated the error, after the control was transferred to "Label" and perhaps some lines of code has already been executed. In case the error happens inside a block (i.e. inside the Then part of an "IF" condition), the "Resume" command will transfer the control flow to the first line following the end of the block. In case of nested block, the control will be transferred after the end of the more external block. Lets see an example:
|
Error Jump1 If (A > B) Then ... ... If (A > B) Then ' This line generates the error and the control flow goes to Jump1 A = B / 0 ... ... EndIf ... ... Else ... ... EndIf 'Resume set the control flow to this point A = B ... ... Jump1: Resume
NB writing something like the following :
... ... Error Jump1 ... ... Error Next ... ...
will happen that the second Error (actually the Error Next) cancel the first (Error Jump1). This means in case of error the command interpreter will refer to the instruction received from Error Next. The last Error cancel all the previous.
In addition also the error condition is reset, which means that it is cancel also the reference to where a possible Resume instruction , would go. In this kind of situation :
Error Jump1 ... ... ... ... Jump1: ........... ... Error Next ... ... Resume ... ...
Resume will have no effect because the line were the error could happened, has been reset because of the instruction Error Next
Let's see how to handle an error with the usual simple example:
Function Main () Dim MyNum As Numeric 'calling function MC to calculate the close average 'from period 1 to 10 MyNum = MC (1, 10) Return MyNum EndFunction
Function MC (PP As Numeric, UP As Numeric) As Numeric ' this function calculates the average of ' closes from PP to UP Dim I As Numeric ' here the default value is 0 Dim A As Numeric Dim S As String = "M"
A = 0 I = (UP - PP + 1) / A I = UP - PP + 1 Return MoveAv(Close, I) EndFunction
In the function "MC" the line
I = (UP - PP + 1) / A
will produce an error of division by zero, because "A" has been set to zero the line before. In this case the command interpreter will terminate program execution exiting from the function which has generated the error (in this case the function "MC") and because there is no Error Handling code, the program will exit also from the Main.
Instead, if the function "MC" has some Error Handling code, the behavior is radically different :
Function Main ()
Dim MyNum As Numeric
'calling the function MC to calculate the average close 'from period 1 to 10
MyNum = MC (1, 10) If MyNum = -1 Then MyNum = 1000 EndIf Return MyNum EndFunction
Function MC (PP As Numeric, UP As Numeric) As Numeric ' this function calculates the average of ' closes from PP to UP Dim I As Numeric ' here the default value is 0 Dim A As Numeric Dim S As String = "M"
Error ExitWithError A = 0 I = (UP - PP + 1) / A I = UP - PP + 1 Return MoveAv(Close, I) ExitWithError: Return -1 EndFunction
In this case the error condition is activate from the line :
Error ExitWithError
In practice, with this line the command interpreter in case there is an error has to transfer the control to the line which has the label "ExitWithError" "Return -1". Doing so the function will return a value (-1 in this case), which can be recognized from the calling function (Main in this example) and act accordingly.
It is also possible to manage the error condition differently, for example ignoring it. The function "MC" will be as following:
Function MC (PP As Numeric, UP As Numeric) As Numeric ' this function calculates the average of ' closes from PP to UP Dim I As Numeric ' here the default value is 0 Dim A As Numeric Dim S As String = "M"
Error ExitWithError A = 0 I = (UP - PP + 1) / A I = UP - PP + 1 Return MoveAv(Close, I) ExitWithError: Resume EndFunction
Or even better:
Function MC (PP As Numeric, UP As Numeric) As Numeric ' this function calculates the average of ' closes from PP to UP Dim I As Numeric ' here the default value is 0 Dim A As Numeric Dim S As String = "M"
Error Next A = 0 I = (UP - PP + 1) / A I = UP - PP + 1 Return MoveAv(Close, I) EndFunction
Once the use has fully grasped this technique, it can manage errors very efficiently, changing the error handling inside the same function. It could be the case where there is the need to handle the same error in two different ways depending on where it occurred. Let's see a small example using always the same function "MC":
Function MC (PP As Numeric, UP As Numeric) As Numeric ' this function calculates the average of ' closes from PP to UP Dim I As Numeric ' here the default value is 0 Dim A As Numeric Dim S As String = "M"
Error Next A = 0 I = (UP - PP + 1) / A Error ExitWithError I = UP - PP + 1 Return MoveAv(Close, I) ExitWithError: Return -1 EndFunction
In this case, on the first two lines after "ErrorNext" if there is an error it will be ignored and the execution continue with the following line. If the error occur after the line " Error ExitWithError" the control will be transfer to the label "ExitWithError".
|