Rebol2's "Hot Errors" (Abandoned by R3-Alpha, Red)

I'll reiterate that I'm quite firm on the importance in discerning:

  • interceptable hot ERROR! by contract "multiplexed" in a function's return value (in the spirit of Rust Result, Haskell Either)

  • "non-interceptible" panics (exceptions)

...and that I think it was a major mistake in R3-Alpha and Red to fuse these into an "all-exceptions" model. That glommed typos and arbitrarily deep errors into the same handling.

But I've also stressed that "hot errors" raise some puzzling issues in handling, that need some care. For instance, just testing for them...

rebol2>> boom: func [] [return make error! "Boom"]

rebol2>> integer? boom
== false

rebol2>> even? boom
** Script Error: even? expected number argument of type: number char date money time

There you see that INTEGER? is the kind of function that's willing to gloss over the fact that a "hot" error happened, because its argument is "ANY-TYPE!"

But EVEN? didn't work because of a type error.

What if we wrote our own versions of INTEGER? and EVEN?

>> my-integer?: func [x] [integer! = type? x]

>> my-integer? boom
** User Error: Boom
** Near: return make error! "Boom"

>> my-even?: func [x] [0 = mod x 2]

>> my-even? boom
** User Error: Boom
** Near: return make error! "Boom"

It seems that if you don't have a type constraint, the ERROR! is promoted to a "panic". But if you have a type constraint that doesn't include ERROR!, it will behave like a typechecking error.

Let's try adjusting those with type constraints and see what happens:

>> my-integer?: func [x [any-type!]] [integer! = type? x]

>> my-integer? boom
== false

>> my-even?: func [x [integer!]] [0 = mod x 2]

>> my-even? boom
** Script Error: my-even? expected x argument of type: integer

Ren-C Concept: Type Checks Bubble ERROR!

I'm not that comfortable with:

rebol2>> integer? boom
== false

That seems much too likely to gloss over a misunderstanding of an error condition.

So I proposed type checks propagating ERROR! instead of returning logic on ERROR! input... (with the obvious exception of ERROR? giving a logic).

With Ren-C's definition of TRY (convert ERROR! to NULL, pass through other values) you can then say try integer? boom and that will defuse the error which propagates, getting you your false result. It looks better than integer?:relax boom or similar, and is strictly more powerful.