This simulates an occurrence of the error EventId inside a call to Culprit in Module. 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/3 succeeds as well. If the handler fails or calls throw/1, then so does error/3.
Not that when the error handler ignores the module (ie. has arity less than three), then error/2 and error/3 are equivalent.
Success:
?- error(68, length(X, Y), lists).
calling an undefined procedure eclipse:length(X, Y) in module lists
% writing an alternative error handler for undefined predicates:
?- arg(1,2). % we want to change this
calling an undefined procedure arg(1, 2) in module eclipse
?- [user]. % compile the new handler
undef_handler(_, Goal, _Context, Module) :-
functor(Goal, Name, BadArity),
(
current_predicate(Name/Arity)@Module
;
current_built_in(Name/Arity)@Module
),
!,
printf("%w does not exist, but there is %w\n",
[Name/BadArity, Name/Arity]),
fail.
undef_handler(Err, Goal, Context, Module) :-
error(default(Err), Goal, Context, Module).
user compiled 592 bytes in 0.02 seconds
yes.
?- set_event_handler(68, undef_handler/4).
yes.
?- arg(1,2). % check if it works
arg / 2 does not exist, but there is arg / 3
no.
Error:
error(N,dummy(1),eclipse). (Error 4).
error(5.0,dummy(1),eclipse). (Error 5).
error(-2,dummy(1),eclipse). (Error 6).
error(95,dummy(1),eclipse). (Error 6).