While many languages speak of "throwing" and "catching" errors, this isn't how Rebol uses the terms.
Instead, it's a generic way to move values up the stack. It gives you a handy "out" from control flow:
result: catch [
if condition [throw result]
some code
case [
condition [more code]
condition [more code, throw result]
]
additional code ; last value falls out of CATCH
]
The implementation of the feature is lightweight, and built on the same mechanic as RETURN. You could in fact use RETURN to do the same thing:
result: eval func [] [
if condition [return result]
some code
case [
condition [return code]
condition [more code, return result]
]
additional code
return result
]
You can, if you like, THROW an ERROR! antiform, and CATCH it. But that's just because you can throw anything. Packs are fine, too:
>> [a b]: catch [
case [
1 = 2 [throw pack [10 20]]
1 = 1 [throw pack [100 200]]
]
]
== 100
>> a
== 100
>> b
== 200
So it's really about throwing whatever you like--not specific to errors or error handling.
THROW and CATCH are a great lightweight feature for control flow, that people really should be using more often than they do. (Ren-C uses "definitional throw", which means there's no risk of you calling a routine that would accidentally catch a throw that wasn't meant for it--which is quite important!)
Exceptions use PANIC+RESCUE
Generally speaking, it's not a good idea to react to exceptions (unless you are something like the CONSOLE, where all you are doing is reporting that the exception happened.)
An error antiform will decay to an exception if it isn't triaged. But you can also cause an exception using PANIC.
(Fun tidbit: PANIC is implemented by making an error antiform and then not triaging it before passing it on. Right now it passes it to NULL?, which doesn't use a meta-aware parameter convention so it forces decay to an exception. panic: cascade [fail/ null?/])
To help emphasize that you should generally not be reaching for the RESCUE routine to recover from abrupt failures, it lives in sys.util.
>> sys.util/rescue [
foo: func [argument] [
return argment + 20 ; whoops, typo
]
foo 1000
]
== make error! [
type: 'Script
id: 'unassigned-attach
message: '[:arg1 "word is attached to a context, but unassigned"]
near: '[
return argment ** + 20]
where: '[foo enrescue eval rescue eval catch* enrescue eval rescue console]
file: ~null~
line: 2
arg1: 'argment
]
Hopefully it's clear to anyone--upon light reflection--why thinking you can handle exceptions is generally misguided!