Exception Handling - the try Statement
|
Description
|
|
try <tryStatSeq>
|
| catch <catchStrings> : <catchStatSeq> |
|
| finally <finalStatSeq> |
|
end
|
|
|
|
Note: | | indicates an optional phrase.
|
•
|
The try statement provides a mechanism for executing statements in a controlled environment, where errors will not just cause the execution to halt with no warning.
|
•
|
When execution enters a try statement, tryStatSeq is executed. In the definitions of terms above, the tryStatSeq is the "code block" in which we are trying to catch exceptions.
|
•
|
If no exception occurs during the execution of tryStatSeq, execution continues with finalStatSeq (if a finally clause was specified). After that, execution continues with the statement after the end keyword.
|
•
|
If an exception does occur during the execution of tryStatSeq, execution of tryStatSeq terminates immediately. The exception object that corresponds to the exception is compared against each catchString in turn until a match is found.
|
•
|
If a matching catch clause is found, the catchStatSeq of that catch clause is executed, and the exception is considered to have been caught. If no matching catch clause is found, the exception is considered not-caught, and is re-raised outside the try construct.
|
•
|
A catchStatSeq can contain an error statement with no arguments, which also re-raises the exception.
|
•
|
When an exception is re-raised, a new exception object is created that records the current procedure name, and the msgString and msgParams from the original exception.
|
•
|
Under normal circumstances, the finalStatSeq of the finally clause (if there is one) is always executed before the control leaves the try statement, whether an exception occurs, whether an exception that does occur is caught, and whether another exception occurs in the catch clause if the exception is caught. This is true even if a catchStatSeq re-raises the exception, raises a new one, or executes a return, break, or next statement.
|
•
|
If an exception is raised in a catch clause and this exception is caught by the debugger and the user exits the debugger, the user's command to stop execution overrides everything, and the finalStatSeq is not executed.
|
•
|
The finalStatSeq is also not executed if one of the following untrappable exceptions occurs:
|
|
Computation timed out (this can only be caught by timelimit, which raises a "time expired" exception, which can be caught).
|
|
Computation interrupted (user pressed Ctrl+C, Break, or equivalent).
|
|
Internal system error (which indicates a bug in Maple itself).
|
|
ASSERT or return type or local variable type assertion failure (assertion failures are not trappable because they indicate a coding error, not an algorithmic failure).
|
|
Stack overflow (when that happens, generally stack space is insufficient for doing anything like running cleanup code).
|
•
|
An error that occurs during simplification of the try statement itself will not be caught, and the finally clause, if any, will not be executed, because the try statement is not yet being executed at that point.
|
•
|
If an exception occurs during the execution of a catchStatSeq or the finalStatSeq, it is treated in the same way as though it occurred outside the try...end statement entirely.
|
•
|
When looking for a matching catch clause, the following definition of "matching" is used:
|
|
Neither the exception object nor the catchStrings are evaluated. (The exception object will already have been evaluated by the error statement that produced it.)
|
|
The catchStrings are considered to be prefixes of the exception object's msgString. If a catchString has n characters, only the first n characters of the msgString have to match the catchString. This allows one to define classes of exceptions.
|
|
A missing catchString will match any exception.
|
|
The "result" of a try statement (the value that % would return if evaluated immediately after execution of the try statement) is the result of the last statement executed within the try statement.
|
•
|
A given catchString (or a catch clause without one) can appear only once in a try...end construct.
|
|
|
Examples of try-catch Statements
|
|
|
Try one method, and if it fails by executing error "FAIL", try a second method:
|
>
|
try
result := MethodA(f,x)
catch "FAIL":
result := MethodB(f,x)
end try;
|
|
Read lines from a file, making sure the file is closed even if something goes wrong while processing the lines:
|
>
|
f := fopen("myfile",READ,TEXT):
|
>
|
try
line := readline(f);
while line <> 0 do
ProcessContentsOfLine(line);
line := readline(f)
end do
finally
fclose(f)
end try;
|
|
Write lines to a file. If something goes wrong, print a message and then re-raise the exception. Close the file no matter what happened.
|
>
|
f := fopen("myfile",WRITE,TEXT):
|
>
|
try
for i to 100 do
fprintf(f,"Result %d is %q\n",i,ComputeSomething(i))
end do
catch:
fprintf(f,"Something went wrong: %q\n",lastexception);
error
finally
fclose(f)
end try;
|
|
|