It is often useful to be able to catch an error that an expression raises, to keep the error from aborting the whole task, and to keep on running as if the expression had returned some other value normally. The following expression accomplishes this:
` expr-1 ! codes => expr-2 '
Note: the open- and close-quotation marks in the previous line are really part of the syntax; you must actually type them as part of your MOO program for this kind of expression.
The codes part is either the keyword
ANY or else a
comma-separated list of expressions, just like an argument list. As in an
argument list, the splicing operator (`@') can be used here. The
=> expr-2 part of the error-catching expression is optional.
First, the codes part is evaluated, yielding a list of error codes that
should be caught if they're raised; if codes is
ANY, then it is
equivalent to the list of all possible MOO values.
Next, expr-1 is evaluated. If it evaluates normally, without raising an error, then its value becomes the value of the entire error-catching expression. If evaluating expr-1 results in an error being raised, then call that error E. If E is in the list resulting from evaluating codes, then E is considered caught by this error-catching expression. In such a case, if expr-2 was given, it is evaluated to get the outcome of the entire error-catching expression; if expr-2 was omitted, then E becomes the value of the entire expression. If E is not in the list resulting from codes, then this expression does not catch the error at all and it continues to be raised, possibly to be caught by some piece of code either surrounding this expression or higher up on the verb-call stack.
Here are some examples of the use of this kind of expression:
`x + 1 ! E_TYPE => 0'
x + 1 if
x is an integer, returns
not an integer, and raises
x doesn't have a value.
`x.y ! E_PROPNF, E_PERM => 17'
x.y if that doesn't cause an error,
doesn't have a
y property or that property isn't readable, and raises
some other kind of error (like
`1 / 0 ! ANY'