R3-Alpha’s TRY added a refinement /EXCEPT for passing in a block or function to act as a handler in the case of an error being raised. It struck me as a clunky attempt to parrot existing terminology. TRAP was created to be a seemingly better name than “TRY”. It appeared to have more parity with CATCH, and TRAP/WITH paralleled CATCH/WITH.
I think the name is an improvement. And it paved the way for the short word TRY to fill an important role in converting nulls to blanks.
But there’s a pattern in both of these constructs which is that they return a result whether something is caught or trapped or not.
>> catch [10 + 20] == 30 >> error? trap [make error! "this is *not* a trapped error"] == #[true]
That particular behavior of trap is particularly tricky because many cases check if a result is an ERROR? and use that as a detection of if a FAIL ran…and here we see that’s not actually happening.
So if you’re trying to write truly “correct” code that uses a TRAP or a CATCH, you pretty much wind up writing a TRAP/WITH or a CATCH/WITH…providing a function taking an error.
But I’ve been questioning the value of this mixing-up-of-return-results. If you want to get a value out of the block, why not do that by setting a variable? You’re usually trying to set a variable anyway, e.g.
value: trap [...], what’s wrong with moving it into the code?
trap [ value: some-calculation-that-may-fail ... ] then func [e] [ ... code to handle the error ... ] else [ ... stuff to do if there was no error ... ... assume value is good ... ]
This cleanly separates out the code paths, allowing usage of null-sensitive constructs. So it means getting rid of the /WITH refinement on TRAP and CATCH, instead using normal THEN/ELSE/etc. constructs with them:
>> catch [10 + 20] // null >> trap [make error! "not a thrown error"] // null
In the case of CATCH, you can always just throw your final result, to get it to conflate with an ordinary throw (this is inexpensive.)
TRAP can’t do that (since it would only be able to return errors). Though you could piggy-back on CATCH if you really wanted to avoid variable declaration with a TRAP…just throw your result:
catch [trap [... throw result] then e => [e]]
I’m not opposed to the idea of code-golf-friendly constructs which could go ahead and do this squashing of results together. (CATCH-DO, TRAP-DO?) But the clean expression with only returning the caught or trapped thing–and null otherwise–seems quite appealing to me for the primitive building block.
Also note: the existence of ENTRAP
I made ENTRAP to address the problem of distinguishing errors from other values, by returning ordinary values enclosed in a block (unless it’s null, which can’t be put in blocks, so the entrapped thing is just null)
>> entrap [null] // null >> entrap [10 + 20] ==  // note it's in a block! >> error? entrap [1 / 0] == #[true] // it's just a plain ERROR! value, not in a block >> block? entrap [make error! "abc"] == #[true] // it's a block that contains an error (since it wasn't FAIL'd)
I don’t know how that fits into the naming and scheme of things, but mentioning it.