With definitional errors, the landscape changes considerably for how we think about error handling.
In this world, there are not a lot of good reasons to use what we've been calling "TRAP". (historical Redbol's TRY). I will call it TRAP/ABRUPT for clarity, since we now have definitional TRAP.
By its design, TRAP/ABRUPT will intercept any error in code at any depth. I've shown that when ATTEMPT was based on this, it was not good:
>> attempt [print "Attempting to read file" read %nonexistent-file.txt]
Attempting to read file
== ~null~ ; anti
>> attempt [print "Attempting but made typos" rread %nonexistent-file.txt]
== ~null~ ; anti
That's fixed now, because ATTEMPT is based on REDUCE-EACH with a ^META variable.
But back to TRAP/ABRUPT. The problem isn't just about typos. It's about the illusion that there's something you can do to react to an arbitrary error...when the constructs you were using didn't even understand it well enough to pipe it through to their output.
In almost all cases, an error intercepted by "TRAP/ABRUPT" cannot be reacted to sanely...it has to be reported.
It's for this reason that languages like Rust pretty much enforce a panic
And our case is even more compelling. For example: How many places is it ever a good idea to sweep a typo under the rug, and just run some other code?
The few cases it's legitimate are things like the console...where you intercept the error and present it, so the user knows it happens and can do something about it. This sort of thing is nearly the only legitimate usage of TRAP/ABRUPT.
Might We Make It Look More "Special" To Discourage Use?
I thought at minimum we should move it to a place that shows it's more of a "system utility" than a "language feature".
So calling it SYS.UTIL.RESCUE
would be a step in that direction.
Things to think about. Anyway, I've made some progress on definitional errors in the scanner and with TO and MAKE operations, so some of the things people like to intercept (like conversions) should work correctly with attempt now.
For instance, in this finite-integer world... an out of range error:
>> attempt [to integer! "10483143873258978444434343"]
== ~null~ ; anti
>> attempt [to intgeer! "10483143873258978444434343"]
** Script Error: intgeer! word is attached to a context, but unassigned
>> to integer! "10483143873258978444434343" except e -> [print ["Error:" mold e]]
Error: make error! [
type: 'Script
id: 'bad-make-arg
message: ["cannot MAKE/TO" :arg1 "from:" :arg2]
near: [to integer! "10483143873258978444434343" ** except e -> ***]
where: [to args]
file: '
line: 1
arg1: #[datatype! integer!]
arg2: "10483143873258978444434343"
]
Should be a more specific error, now that I look at that. But I guess it just wasn't.