Instantiation categories
Lists, Sets and Instructions
Exception Handling
array

Exception Handling

Exceptions are a useful feature of software development: they are used to describe an exceptional or wrong behavior of a block. Exception can be raised, to signal this behavior and are caught by exception handlers that surround the code where the exceptional behavior happened. Exceptions are CLAIRE objects (a descendent from the class exception) and can contain information in slots. The class exception is an "ephemeral" class, so the list of instances is not kept. In fact, raising an exception e is achieved by creating an instance of the class e. Then, the method close is called: the normal flow of execution is aborted and the control is passed to the previously set dynamic handler. A handler is created with the following instruction :
 try <expressioncatch <class> <expression>
For instance we could write :
 try 1 / x
 catch any (printf("1/~A does not exists"x), 0)
A handler "try e catch c f", associated with a class c, will catch all exceptions that may occur during the evaluation of e as long as they belong to c. Otherwise the exception will be passed to the previous dynamic handler (and so on). When a handler "catches" an exception, it evaluates the "f" part and its value is returned. The last exception that was raised can be accessed directly with the exception!() method. Also, as noticed previously, the body of a handler cannot contain a break statement that refers to a loop defined outside the handler.

The most common exceptions are errors and there is a standard way to create an error in CLAIRE using the error(s:string, l:listargs) instruction. This instruction creates an error object that will be printed using the string s and the arguments in l, as in a printf statement. Here are a few examples :
 error("stop here")
 error("the value of price(~S) is ~S !"xprice(x))
Another very useful type of exception is contradiction. CLAIRE provides a class contradiction and a method contradiction!() for creating new contradictions. This is very commonly used for hypothetical reasoning with forms like :
 try (choice(), // create a new world
     ...)       // performs an update that may cause a contradiction
 catch contradiction
     (backtrack(), // return to previous world
     ...)
In fact, this is such a common pattern that CLAIRE provides a special instruction, branch(x), which evaluates an expression inside a temporary world and returns a boolean value, while detecting possible contradiction. The statement branch(x) is equivalent to :
 try (choice(),
     if x true else (backtrack(), false))
 catch contradiction (backtrack(), false)
If we want to find a value for the slot x.r among a set x.possible that does not cause a contradiction (through rule propagation) we can simply write :
 when y := some(y in x.possible | branch(x.r = y))
 in x.r := y
 else contradiction!()