Yes. It went away from the original problem for dealing with the specific errors from assert/1. It is relevant though. assert/1 for example may raise resource errors as well as type, representation and instantiation errors. These typically need to be handled differently. Subsequently the discussion went to the expect API, which IMO deals with where and how errors are handled, not about how to handle the different errors. I added the intercept/3, delimited continuations and a bit more as alternatives to handle exceptional cases depending on the context. The approach is a bit different. Where (simplified) the expect API passes unexpected events as data terms, and leaves the processing of these terms to later stages, the intercept/3 approach tells the lower level how to behave on certain unexpected events (although it can also be used for normal events).
I do not (yet) understand the railway-oriented programming concept well enough to see how this connects.
I do think there are two issues in this discussion:
- How to handle different errors elegantly. Ideally that should also ensure that errors you do not want to handle can be recognised as such by the system such that it can immediately start helping the developer to debug the issue.
- (Decide) where to handle unexpected events (catch, expect, intercept, etc.)
Note that also the expect interface should distinguish such cases. In @pmoura’s blog entry, a missing father/mother can also be caused by a resource exception. That is most likely not what you want. I know, you can work around that using the different
expected constructors … It occurs to me that the API deal well with passing unexpected events along using a stream. Safely distinguishing expected, unexpected and really unexpected (e.g., resource errors, undefined predicates, …) is a different matter that should probably be addressed in a different library.