A la
try
foo()
catch e::ArgumentError
# hey, I know how to recover from an ArgumentError!
catch e::AssertionError
# I also know how to recover from an AssertionError!
catch e
# hmmm, anything else is probably fatal
rethrow(e)
end
I know there have been (hotly debated) grand visions of error-handling laid out in #7026 and #15514, but as far as julia 1.0, I think we should at least support catching specific errors. My latest methodology for error-handling goes something like:
The only issue w/ this approach is I end up w/ code like:
try
foo()
catch e
typeof(e) <: ArgumentError && recover_from_argumenterror() # hey, I know how to recover from an ArgumentError!
typeof(e) <: AssertionError && recover_from_assertionerror() # I also know how to recover from an AssertionError!
# hmmm, anything else is probably fatal
rethrow(e)
end
which is decidedly less pleasant. I feel like having just a little extra syntax could go a long way to making error-handling feel a little more grown up in julia.
Any idea on how hard this would be? Where to start looking to implement?
Duplicate of #1075.
If we do this, it could be implemented entirely in the front end. First the parser would have to be modified to accept multiple catch blocks, then these would be lowered into if
statements and rethrow
.
What if instead of catch e::type
we have catch f(e) -> ::Bool
or catch e if Bool expr
try
foo()
catch e -> e isa NetworkError
...
catch e -> e isa HTTPError && e.code == 404
...
end
try
foo()
catch e if e isa NetworkError
...
catch e if e isa HTTPError && e.code == 404
...
end
Catching on a Bool function (or expression) is more flexible than catching on types, and not very much more verbose for cases where the expression is just e isa FooType
Also can we have a retry
keyword too? :)
See https://github.com/samoconnor/Retry.jl
_[updated: changed :>
to isa
, thanks @quinnj]_
The problem in your example @samoconnor is you're missing e
as a value and a type: i.e. e <: NetworkError
suggests e
is a type, whereas e.code == 404
assumes it's the object itself. I say we keep this as simple as possible to make catching specific exception types cleaner. e::SpecificExceptionType
is nice because it matches current behavior (and indeed, it looks like it's currently an error on master, which means it's not changing existing behavior). After you catch e::HTTPError
, it seems reasonable to then do your own "business logic" within that specific catch block. I'm not aware of any other language that allows full on boolean expressions when catching.
@quinnj thanks for spotting e <:
, my intention was e isa
, I'll update the examples above...
@JeffBezanson, @StefanKarpinski Here's another possibility with a smaller change and the same intention of reducing unintended over-catching....
What if rethrow(::Exception)
was removed and replaced with its opposite delete!(::Exception)
.
i.e. catch
would no longer consume exceptions by default, it would rethrow them unless deleted.
julia> try
foo()
catch e
println("Whoops foo() said: $e")
end
Whoops foo() said: UndefVarError(:foo)
ERROR: UndefVarError: foo not defined
vs
julia> try
foo()
catch e
println("Whoops foo() said: $e")
delete!(e)
end
Whoops foo() said: UndefVarError(:foo)
The example above would become:
try
foo()
catch e
if e isa NetworkError
...
delete!(e)
elseif e isa HTTPError && e.code == 404
...
delete!(e)
end
end
With this feature you might change #15906 to be "Undeleteable exceptions"...
try
foo()
catch e
delete!(e)
end
ERROR: OutOfMemoryError is not deletable.
(Maybe delete(e, force=true)
could be supported too.)
@quinnj I feel pretty strongly that catch-by-type is a half-way solution, and that we should be able to do better than what Java did 20 years ago.
As an example, with AWS stuff I end up with lots of non-type filtering like this:
But I feel like you're just hijacking this feature request, which was intended to be minimal and hopefully easily accepted. You're basically just reproposing #15906, which you can and should discuss on those threads.
I'd rather we at least do the simple thing first, which, again, should hopefully be easily accepted by everyone before we try re-inventing error-handling. Don't get me wrong, grand visions and creative functionality have their place, but I'm just trying to push for a basic language feature that most other languages support.
Sorry @quinnj, I didn't mean to make you feel like your request was hijacked.
No worries. I understand you're passionate about error-handling and that's great. I'm just worried about a simple feature request turning into #7026 or #15514, which were much more hotly debated. I'm hoping for a "quick win" here.
How is progress on this subject?
Yeah, this is crazy that such a feature is not already supported...
Most helpful comment
Yeah, this is crazy that such a feature is not already supported...