REBOL3 tracker
  0.9.12 beta
Ticket #0002133 User: anonymous

Project:

Previous Next
rss
TypeIssue Statussubmitted Date8-Mar-2014 22:26
Versionr3 master CategoryError Handling Submitted byBrianH
PlatformAll Severityminor Prioritynormal

Summary [Epic] Errors are your friends
Description "Errors are your friends" is one of the most important principles of Rebol 3. This rule has caused us to change a lot of functions, including comprehensive semantic changes like the none propagation rebalancing, or the binary conversions revamp. It touches everything in Rebol.

Here are the basic rules:
- Errors should be useful, and only for erroneous conditions. Those are friendly.
- Good errors are informative. Be sure to pick the right error.
- Good errors lead you to the root cause. Have better error locality, when it's safe.
- For situations where there is a useful, sensible interpretation for it not being an error, don't trigger an error. Debatable errors aren't your friends.
- Don't be presumptuous. For some situations it's not your choice whether they are erroneous. Do something less drastic.
- Unpredictable errors are bad errors. If an error is supposed to be triggered, make sure it is. No silent failures.
- Bad errors are not your friends. Zero tolerance for bad errors.

The main reasons for triggering errors are to keep you safe and help track down bugs, in that order. Any errors that don't contribute to those should be changed to better errors, or redefined as being less erroneous. Errors need to be your friends, or else they are gone. Zero tolerance.

The main benefits that good errors give us:
- Better debugging means faster development.
- Less error-handling code needed.
- Code is safer overall, especially when compared to when we have bad errors, dealing with which can hide good errors.
- It's easier to improve things in the future, by marking the erroneous stuff as such now. That frees up the scenario for future enhancement without worrying as much about backwards compatibility. Particularly in non-extensible dialects like PARSE.

You don't have to trigger an error! specifically, we have two other levels which can be much better in many cases:
- The none! type, a placeholder-value meaning nothing, where nothing is usually (but not always) not an error.
- The unset! type, the explicit non-value. The main purpose of unset! is to trigger errors, but later on, when that makes the errors better.

The control code needed to deal with errors is really heavy-weight, with a lot of overhead, and if you're using errors for non-erroneous situations the workaround code can inadvertently hide the real errors. This is bad, definitely not friendly.

In contrast, most regular control code can deal with nones quite efficiently - none is just falsey to conditional functions. It is easy to deal with nones. So in cases where it was safe to do so, or where the errors were more ambiguous, we decided to return none instead. And in some safe cases, we decided to allow some functions to return none when they are passed none, a process known as "none propagation". Getting the right balance of none propagation is tricky, but the effort has made Rebol a lot nicer to use, and faster too.

We've also made more functions better able to deal with unset! values, and made them able to be accessible through get-words, rather than needing to use GET/any. This makes it easier to make certain types of functions less presumptuous. In particular, bulk series operations need to be less presumptuous, since propagating unsets in that case can lead to the errors they trigger later being easier to trace back to the root cause. This helps enhance the use of unsets to delay-trigger better errors. And for when that unset wasn't really an error, we have TO-VALUE to change it to a nice friendly none.

Another part of this principle is realizing that in Rebol, the main purpose of function type specs is to trigger errors - documentation is secondary, and it doesn't affect allocation at all. Those errors are features of the function, and they need to be as carefully planned as any of its other features. They even make it possible to optimize your function, because those friendly errors that were triggered earlier protect you from having to deal with the iffy data that they were blocking.

We've even added a function with the sole job of triggering the friendly errors you need to protect you: ASSERT. We've added better support to TRY to handle the errors you get. We've made it safe to handle error values after they're caught, by disarming them immediately, no DISARM function needed.

That's the principle. This ticket is not only to explain the principle, but also to collect references to relevant tickets where we applied this principle, and also to have a to-do list of things we missed or which are still under debate.

To-do list below, with statuses. Documentary list after that.
Example code

			

Assigned ton/a Fixed in- Last Update8-Mar-2014 22:43


Comments
(0004360)
BrianH
8-Mar-2014 22:26

To-do list to come.
(0004361)
BrianH
8-Mar-2014 22:26

Documentary list to come.

Date User Field Action Change
8-Mar-2014 22:43 BrianH Description Modified -
8-Mar-2014 22:26 BrianH Comment : 0004361 Added -
8-Mar-2014 22:26 BrianH Comment : 0004360 Added -
8-Mar-2014 22:26 BrianH Ticket Added -