# Errors considered harmful

**URL:** <https://swi-prolog.discourse.group/t/errors-considered-harmful/3574>\
**Category:** Request For Comments\
**Created:** [February 8, 2021, 5:54pm UTC](https://swi-prolog.discourse.group/t/errors-considered-harmful/3574 "2021-02-08T17:54:43Z")\
**Posts on this page:** 1\
**Showing post:** 88

<div class="post-metadata">

**Author:** ![ridgeworks](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/ridgeworks/32/886_2.png) [@ridgeworks](https://swi-prolog.discourse.group/u/ridgeworks)\
**Post date:** [February 15, 2021, 4:21pm UTC](https://swi-prolog.discourse.group/t/errors-considered-harmful/3574/88 "2021-02-15T16:21:45Z")

</div>

> [@jan](#):
>
> built-ins tend to call PL\_type\_error() or PL\_domain\_error() and return failure, so that should not be a big issue.

Built-ins are my primary concern but perhaps I’m misunderstanding. In `pl-prims.c` there are 45 calls to `PL_error`, not including another 5 calls to `PL_type_error`, 3 to `PL_domain error`, and 5 more to `PL_representation` error. Do these not generate exceptions rather than failures? I don’t know how many of these would reasonably mean logical failure, but I suspect there’s quite a few.

Libraries and user code are an issue, but one I think, as a programmer, have some control over. On the other hand I’m stuck with the built-ins, they can’t be redefined. Furthermore, I don’t have the same performance concerns calling a library predicate vs. calling a builtin.

> [@jan](#):
>
> The biggest problem is confining this.

Agreed, but it would be nice to have something to confine. If the default is the status quo I don’t see the risk. If step one was (optionally) no confinement, what exactly would break? Since most programs don’t normally(?) depend on these kinds of low level exceptions from builtins for proper execution, that leaves those with catches of the types of errors I’m interested in. Of those, the ones that just fail are fine. The remaining are those whose proper operation depends on handler code. Obviously those programs wouldn’t change the default without careful consideration.

Bottom line: it’s not obvious to me that a no confinement would be that bad. I barely understand enough about the module system to use it, let alone whether it can be used to contain this kind of semantics.

> [@jan](#):
>
> All in all, I think the most practical solution is to define goal expansion for the predicates that you want to fail silently

And this is a possible route I’m willing to explore. But I think it still has a few issues. Just considering the built-ins, there are almost 60 potential exceptions for consideration. It would be extremely helpful if these were documented in the predicate semantics. And this should be extended to library predicates as well, especially if the exceptions are thrown transitively from built-ins. (So document at least; Java, and others, think this important enough to be part of the method/function syntax.)

The second issue is that in majority of existing cases, the guards are already in place due to the usual necessity of avoiding exceptions in running code. So, for working code at least, the checks would actually be done 3 times: in the original code, in the expanded code, and in the builtin to detect the conditions to throw the exception.

Thirdly, and perhaps my failing, I don’t understand the containment semantics of goal\_expansion.

> [@jan](#):
>
> Built-in support seems a little too hacky to pollute the core system

How so? There seem to be a limited number of `PL_error`-like functions. Check a flag, if true continue with existing code, else fail. (Probably a gross over-simplification, I know.)

> [@jan](#):
>
> The main use case I get from your examples is a rather uncontrolled form of overloading of operations.

I don’t relate to this description at all. If I inserted a guard to avoid calling a builtin that might generate an exception, that’s just (premature) failure. I just want to avoid the necessity of the guard. That’s a pretty typical use case isn’t it?

> [@jan](#):
>
> The DSL can deal with the necessary error handling and/or rewrite to avoid the errors.

Only with a fair amount of work and the result still has a containment issue (does it not?) and incurs some level of overhead (probably acceptable in most cases, but irksome).

> [@jan](#):
>
> Flags that change global behavior are a proven recipe for problems

Any examples of those that cause problems? I can think of flags that do this, but I’m not aware of any specific problems. And this particular use seems fairly limited to me.

I freely admit I don’t understand all the ramifications of what I’m proposing so here’s another idea that could be used to implement my objective, albeit at some cost. Permit `user:exception` to be a handler of last resort for any exception. That would permit the addition of a global handler to optionally turn any exception into a failure under my control.

Aside: If that passes muster, I would also like the option of succeeding (`Action=succeed`) like a normal catch handler so at some point I could turn an instantiation error into a constraint. And yes, that’s not Prolog, but it is logic programming.

---

_[View the full topic](https://swi-prolog.discourse.group/t/errors-considered-harmful/3574)._
