What will we cover? |
---|
|
Traditionally when programmers do something, call a function say, the result of the function can be tested for validity. For example if you try to open a file that doesn't exist the return value might be a NULL value. There are two common strategies for dealing with these kinds of situations:
In either case its up to the programmer to check to see whether an error has occurred and take appropriate action.
IN BASIC this looks like:
OPEN "A:\DATA.TXT" FOR INPUT AS #1 IF ERR = 53 THEN CALL FileNotFoundError ELSE REM CONTINUE WITH FILE HANDLING HERE END IF
This can result in production quality programs where over half of the code is taken up with testing every action for success. This is cumbersome and makes the code hard to read (but in practice it's how the majority of programs today work). A consistent approach is essential if silly mistakes are to be avoided.
In more recent programming environments an alternative way of dealing with errors has developed. This is known as exception handling and works by having functions throw or raise an exception. The system then forces a jump out of the current block of code to the nearest exception handling block. The system provides a default handler which catches all exceptions and usually prints an error message then exits.
The exception handling block is coded rather like an if...then...else block:
try: # program logic goes here except ExceptionType: # exception processing for named exception goes here except AnotherType: # exception processing for a different exception goes here else: # here we tidy up if NO exceptions are raised
There is another type of 'exception' block which allows us to tidy up after an error, its called a try...finally block and typically is used for closing files, flushing buffers to disk etc. The finally block is always executed last regardless of what happens in the try section.
try: # normal program logic finally: # here we tidy up regardless of the # success/failure of the try block
Tcl has a somewhat similar mechanism using the keyword catch:
set errorcode [catch {
unset x
} msg ]
if {$errorcode != 0} {
# handle error here
}
In this case x doesn't exist so we can't unset it. Tcl raises an exception but the catch prevents the program from aborting and instead puts the error message into the msg variable and returns a non-zero value (which can be defined by the programmer). You can then test the return value of catch in errorcode. If it is non zero then an error occured and you can examine the msg variable.
BASIC doesn't quite support exceptions but does have a construct which helps to keep the code clear:
100 OPEN "A:\Temp.dat" FOR INPUT AS #1
110 ON ERROR GOTO 10010
120 REM PROGRAM CODE HERE...
130 ...
10000 REM ERRORHANDLERS:
10010 IF ERR = 54 THEN....
Note the use of line numbers. This was common in older programming languages including early BASIC. Now you can do the same thing with labels:
ON ERROR GOTO Handler
REM Now create divide by zero error
x = 5/0
Handler:
IF ERR = 23 THEN
PRINT "Can't divide by 0"
x = 0
RESUME NEXT
END IF
Notice the RESUME NEXT statements which allow us to return to just after the error and carry on with the program.
What happens when we want to generate exceptions for other people to catch, in a module say? In that case we use the raise keyword in Python:
numerator = 42 denominator = input("What value will I divide 42 by?") if denominator == 0: raise "zero denominator"
This raises a string object exception which can be caught by a try/except block.
In Tcl the return statement takes an optional -code flag which gets caught by any enclosing catch:
proc spam {val} { set x $val return -code 3 [expr $x] } set err [catch { set foo [spam 7] } msg]
err should have the value 3 and msg the value 7. Once again a case where Tcl's syntax is less intuitive than it might have been.
In BASIC you can set the ERR variable with the ERROR statement:
ON ERROR GOTO ERRORS INPUT "INPUT ERROR CODE"; E ERROR E ERRORS: IF ERR = 142 THEN PRINT "Error 142 found" STOP ELSE PRINT "No error found" STOP END IF
Things to remember |
---|
|
If you have any questions or feedback on this page
send me mail at:
alan.gauld@btinternet.com