next up previous contents index
Next: Input/Output Logging Up: DebuggingLogging, and Error Previous: DebuggingLogging, and Error

fail Statement

 

    The fail statment is available for explictly handling errors. fail is an alternate return statement, and it is the only way to generate values of type fail; fail is both a statement and a value type. Values of type fail are unique in that if they are passed as parameters to a function, the function is not invoked, and the result of the function call is the fail value that was passed as a parameter. This property allows fail values, once generated, to be propagated.

Here is a simple example of how fail values are used:

    func divide( dividend, divisor )
        {
        if ( divisor == 0 ) fail "division by zero"
        return dividend / divisor
        }
here the function simply checks for division by zero. So now if this function is called with a divisor of 0:
    func try1(x,y) divide(x,y)
    func try2(x,y) try1(x,y)
    func output(x) { print x }
    output(try2(34,0))
the output would look like:
    <fail>: division by zero
            Stack:  divide()
                    try1()
                    try2()
                    output()
The result contains the message with which fail was called, and the call stack to where the error occurred. Notice that output() does not have to check to verify that it has not been passed a fail value. When a fail value is passed to a function, the function is not invoked, but the return value of the function is the fail value it was passed, and the print out of this value is the output shown.

    The function is_fail() is available to check to see if a value has type fail. If so, this function returns T, otherwise it returns F. This function can be used to immediately propagate fail values; for example (continuing the above example):

    func try3(a,b)
        {
        x := try2(a,b)
        if ( is_fail(x) ) {
            print "problem!"
            fail
            }
        return a + b * 2
        }
    print try3(8,2)
    print try3(8,0)
The output produced by this little code segment would look like:
    12
    problem!
    <fail>: division by zero
        Stack:  divide()
                try1()
                try2()
                try3()
In theory, this use of is_fail() should only be necessary when there are intermediate values produced, here x, on which the return value does not depend. In practice, this may not be the case.


next up previous contents index
Next: Input/Output Logging Up: DebuggingLogging, and Error Previous: DebuggingLogging, and Error

Thu Nov 13 16:44:05 EST 1997