yes, right now in Arc 3.1 if I catch (err "foo") with on-err, I have to use details to extract the string "foo", but with your idea of using raise we'd get the string "foo".
So in this way your idea and my idea would work out the same: both would pass the string "foo" to the handler when (err "foo") was used.
A difference would be primitive errors generated by Racket, with my approach the handler would get the string like "/: division by zero" while with your implementation the handler would still get the exception object.
I don't think we'd want it to matter if errors are generated internally by Arc or Racket, so assuming that we do want to continue to raise errors in Arc with (err "foo") then I'm guessing we'd want to special case Racket exceptions and pass the exn-message string to the handler so that it would end up working the same way.
By the way I don't think you do want to use call-with-exception-handler; if the handler returns then then Racket invokes the next exception handler in the chain, so it's like re-raising the exception. But the with-handlers form works fine with arbitrary values raised by raise.
"I don't think we'd want it to matter if errors are generated internally by Arc or Racket, so assuming that we do want to continue to raise errors in Arc with (err "foo") then I'm guessing we'd want to special case Racket exceptions and pass the exn-message string to the handler so that it would end up working the same way."
That actually makes me wonder if Arc should have access to 'raise as a separate function from 'err. After all, if we catch a Racket exception as a string, we lose information.
For all I know, losing that information isn't so bad. I almost always design code so it never throws exceptions that should be caught, so I don't know what information is useful to have in an exception. I've only encountered two places it makes sense to capture an exception:
- When the exception implements an escape continuation, in which case the necessary information is the unique identity of the catch point.
- When the program is something like a REPL or server that handles multiple commands and should typically recover from an error encountered in any one command. In this case, the necessary information is whether the error should be considered severe enough to take down or restart the particular command loop in progress. The usual approach to representing this information is a hierarchy of types such that, if you say exn:fail is okay, you implicitly say exn:fail:contract:divide-by-zero is okay. Is there a better approach?
---
By the way I don't think you do want to use call-with-exception-handler; if the handler returns[...]
"...the exn:break exception typically should not be caught..."
"Before any predicate or handler procedure is invoked, the continuation of the entire with-handlers expression is restored, but also parameterize-breaked to disable breaks."
Would it be better or worse to switch to 'with-handlers*, which doesn't disable breaks?