`try` blocks, improving their docs

Let’s document the in’s and out’s of try [catch] [finally] end blocks, and the use[s] of each part, the purpose of rethrow and why one would choose to include or exclude either the catch part or the finally part or both. Others know this part of Julia much better than I … getting the correct info here is reasonable way to migrate it into the docs.

What are you missing from

https://docs.julialang.org/en/v1/manual/control-flow/#Exception-Handling-1

?

pictures with flow arrows and contextual conditions

Can you explain what you mean by this? This is the first time I encounter the term.

FWIW, I find this part of the documentation pretty clear, and I think it has examples for the typical patterns one encounters.

Regarding pictures: the manual is pretty thin on these, as they are labor-intensive to create and maintain. I am not sure that there is a compelling need for them here, but perhaps I missed something that is better explained visually.

1 Like

sometimes a picture is easier to see than are words to comprehend

1 Like

Sometimes it is, but it would be great if you could make specific suggestions about what you are missing in that part of the manual.

So far, with 3 posts into this thread, it is not very clear.

If I understood better what I have yet to understand about this, I could be of more direct help (the genesis of this thread is Lost variable assignment in nested try/catch/finally blocks · Issue #31357 · JuliaLang/julia · GitHub).
I thought that others who had worked some of the more subtle aspects of try, throw, catch, rethrow, finally in their parts as much as as a whole approach [which is familiar] could jot a few notes and in the aggregate we could make the docs more fully and easily understood and applied by others who may be new the constructs.

Not sure what is relevant from that issue, it seems to be about an optimizer bug.

You seem to be making the implicit assumption that there is some expert knowledge missing from the docs without being able to articulate what it is. I wonder why.

I would propose that there isn’t anything essential that is missing from the docs, and major common patterns are rather well-documented. Perhaps an extra example with rethrow could help (that is a common pattern for catching just a subset of exceptions), but that’s about it. I see no particular place for graphical illustrations.

Exceptions are in fact not an area where Julia differs from most modern languages with a REPL, if is fairly standard fare.

ok … no worries

The section on finally does a good job of motivating the feature, but describes the semantics a bit too quickly. I’d like to see a fuller explanation of when, exactly, the finally clause is executed, in a variety of situations (e.g. more complicated ones involving nested try/catch/finally blocks). Also, what happens, exactly, if the finally clause itself throws an exception?

1 Like

Good question — it looks like that replaces the other error, which I think makes sense:

function f(x)
    try
        x ≥ 1 && throw(error("too much"))
        x
    finally
        @info "finalizing"
        x ≥ 2 && throw(error("insidious bug"))
    end
end

gives

julia> f(0)
[ Info: finalizing
0

julia> f(1)
[ Info: finalizing
ERROR: too much
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] f(::Int64) at ./REPL[115]:3
 [3] top-level scope at none:0

julia> f(2)
[ Info: finalizing
ERROR: insidious bug
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] f(::Int64) at ./REPL[115]:7
 [3] top-level scope at none:0