This simulates an occurrence of the error EventId inside a call to Culprit. The valid error numbers are those returned by current_error/1. Event names can be any atom as long as an event handler has been defined for them.
If EventId is a structure with functor default/1, the structure argument is taken as the error number and the default handler is executed, even if the error handler has been redefined using set_event_handler/2. This is useful for writing user error handlers.
If the event handler succeeds, possibly binding some variables inside Culprit, then error/2 succeeds as well. If the handler fails or calls exit_block/1, then so does error/2.
error/2 is defined as
error(N, G) :- error(N, G, _).
Success:
% Writing a predicate with type checking
[eclipse]: [user].
is_positive(N) :-
number(N),
!,
N >= 0.
is_positive(N) :-
error(5, is_positive(N)).
user compiled 244 bytes in 0.02 seconds
yes.
[eclipse]: is_positive(a).
type error in is_positive(a)
% changing the behaviour of a built-in by redefining a handler
[eclipse]: //(1,0,X). % change this behaviour
arithmetic exception in //(1, 0, X)
[eclipse]: [user]. % define the new handler
my_handler(_, //(_,_,Result)) :-
!,
Result = infinity.
my_handler(Err, Goal) :-
error(default(Err), Goal).
user compiled 212 bytes in 0.00 seconds
yes.
[eclipse]: set_event_handler(20, my_handler/2).
yes.
[eclipse]: //(1,0,X). % check if it works
X = infinity
yes.
[eclipse]: sqrt(-1,X). % other culprits: as before
arithmetic exception in sqrt(-1, _g36)
Error:
error(N,dummy(1)). (Error 4).
error(5.0,dummy(1)). (Error 5).
error(-2,dummy(1)). (Error 6).