# New syntax suggestion: catch with type specs

**URL:** https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840
**Category:** Internals & Design
**Tags:** exception
**Created:** [July 20, 2023, 1:51pm UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840 "2023-07-20T13:51:14Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [July 21, 2023, 8:37pm UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/21 "2023-07-21T20:37:02Z")

</div>

`begin` is just one kind of block. `try` is also a block.

```julia
julia> ex = :(try
           # do something
       catch e
           e::AssertionError -> println("AssertionError")
           e::InexactError -> println("InexactError")
       end);

julia> ex.head
:try

julia> ex.args[1]
quote
    #= REPL[353]:3 =#
end

julia> ex.args[2]
:e

julia> ex.args[3]
quote
    #= REPL[353]:4 =#
    e::AssertionError->begin
            #= REPL[353]:4 =#
            println("AssertionError")
        end
    #= REPL[353]:5 =#
    e::InexactError->begin
            #= REPL[353]:5 =#
            println("InexactError")
        end
end

```

So we could just do the following which does nothing at the end.

```julia
julia> macro errdispatch(ex)
       end
@errdispatch (macro with 1 method

julia> @errdispatch try
           # do something
       catch e
           e::AssertionError -> println("AssertionError")
           e::InexactError -> println("InexactError")
       end

```

The plan here is

1. Locate the catch block, `ex.args[3]`
2. Find all the statements with a `->` head and turn them info different methods of the same function.
3. Pass e to that function so we can use multiple dispatch.

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [July 22, 2023, 5:12am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/22 "2023-07-22T05:12:18Z")

</div>

Here’s the prototype.

```julia
macro error_dispatch(e)
     _error_dispatch(e)
end
function _error_dispatch(ex)
    catch_block = ex.args[3]
    exception = ex.args[2]
    catch_func = gensym(:catch)
    catch_block.args = map(catch_block.args) do cex
        if cex isa Expr && cex.head == :(->)
            _anon_to_named_func(catch_func, cex)
        else
            cex
        end
    end
    push!(catch_block.args, :($catch_func($exception)))
    esc(ex)
end

function _anon_to_named_func(name::Symbol, anon::Expr)
    @assert(anon.head == :(->))
    func_args = anon.args[1]
    func_body = anon.args[2]
    quote
        $name($func_args) = $func_body
    end
end

```

Here is a demonstration:

```julia
julia> function foo(g)
           @error_dispatch try
               g()
           catch e
               e::AssertionError -> println("Hello. I got an AssertionError!")
               e::InexactError -> println("Hola. ¡Recibí un IneaxctError!")
           end
       end
foo (generic function with 1 method)

julia> foo(()->@assert(false))
Hello. I got an AssertionError!

julia> foo(()->Int(5.2))
Hola. ¡Recibí un IneaxctError!

```

It works by converting all the anonymous functions created in the catch block into methods of the same named function. Then it adds a statement to call that named function with the exception.

```julia
julia> @macroexpand @error_dispatch try
           g()
       catch e
           e::AssertionError -> println("Hello. I got an AssertionError!")
           e::InexactError -> println("Hola. ¡Recibí un IneaxctError!")
       end
:(try
      #= REPL[81]:2 =#
      g()
  catch e
      #= REPL[81]:4 =#
      begin
          #= REPL[74]:6 =#
          var"##catch#310"(e::AssertionError) = begin
                  #= REPL[74]:6 =#
                  begin
                      #= REPL[81]:4 =#
                      println("Hello. I got an AssertionError!")
                  end
              end
      end
      #= REPL[81]:5 =#
      begin
          #= REPL[74]:6 =#
          var"##catch#310"(e::InexactError) = begin
                  #= REPL[74]:6 =#
                  begin
                      #= REPL[81]:5 =#
                      println("Hola. ¡Recibí un IneaxctError!")
                  end
              end
      end
      var"##catch#310"(e)
  end)

```

Should I turn this into a package?

---

<div class="post-metadata">

### Author: ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)
#### Post date: [July 24, 2023, 8:31am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/23 "2023-07-24T08:31:02Z")

</div>

> [@mkitti](#):
>
> Let’s figure out how to make this happen with a macro.
> 
> Here’s the closest valid syntax.
> 
> ```julia
> @errdispatch try
> # do something
> catch e
> e::AssertionError -> println("AssertionError")
> e::InexactError -> println("InexactError")
> end
> 
> ```

That’s a neat looking workaround. May I suggest omitting the `e` after `catch`? It’s slightly misleading, because it suggests that the `e` used in the patterns must be the same variable, but that’s not the case. I think I would like this more if the macro _complained_ if there were an exception variable after `catch`. The macro body could add its own variable (to be passed to the freshly created handler function).

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [July 24, 2023, 7:32pm UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/24 "2023-07-24T19:32:34Z")

</div>

Actually I was thinking of heading in the opposite direction. Essentially, all that I’m doing is allowing one to create methods for an anonymous function. I was wondering it if would be better to be more explicitly like the following instead of doing “magic”.

```julia
try
catch e
    error_handler = @anon_method begin
        e::AssertionError -> println("AssertionError")
        e::InexactError -> println("InexactError")
    end
    error_handler(e)
end

```

---

<div class="post-metadata">

### Author: ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)
#### Post date: [July 24, 2023, 7:52pm UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/25 "2023-07-24T19:52:40Z")

</div>

This latter form would essentially replicate `Match.jl` or `Rematch.jl` behavior:

```julia
try
    ...
catch e
    @match e begin
        e::AssertionError => println("AssertionError")
        e::InexactError => println("InexactError")
    end
end

```

So I guess it would be superfluous in this form.

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [July 25, 2023, 4:14am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/26 "2023-07-25T04:14:00Z")

</div>

There is a very important difference with the macro I published above. It uses multiple dispatch rules and order does not matter. My sense at the moment is that Match.jl and Rematch.jl will match against the first pattern. My method above will use multiple dispatch rules and likely require dynamic multiple dispatch.

---

<div class="post-metadata">

### Author: ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)
#### Post date: [July 25, 2023, 7:10am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/27 "2023-07-25T07:10:46Z")

</div>

You’re perfectly right. How about this form then, to emphasize dispatch, but to reduce boilerplate?

```julia
try
catch e
    @dispatch_error e begin
        e::AssertionError -> println("AssertionError")
        e::InexactError -> println("InexactError")
    end
end

```

**Update:** It doesn’t have to be called `@dispach_error`, it could be `@dispatch_lambda` or plain `@dispatch` as well, since there is no error specific stuff in it.

---

<div class="post-metadata">

### Author: ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)
#### Post date: [July 25, 2023, 9:47am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/28 "2023-07-25T09:47:37Z")

</div>

> [@HanD](#):
>
> ```julia
> @dispatch e begin
> e::AssertionError -> println("AssertionError")
> e::InexactError -> println("InexactError")
> end
> 
> ```

And based on your implementation, here’s how I would do it:

```julia
macro dispatch(expr, body)
    @assert(body isa Expr && body.head == :block,
            "begin ... end block expected in second argument!")
    fn = gensym()
    body = map(body.args) do ex
        if ex isa Expr && ex.head == :(->)
            :($fn($(ex.args[1])) = $(ex.args[2]))
        else
            ex
        end
    end
    return quote
        let $fn
            $(body...)
            $fn($expr)
        end
    end |> esc
end

```

---

<div class="post-metadata">

### Author: ![larsh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/larsh/32/51866_2.png) [@larsh](https://discourse.julialang.org/u/larsh)
#### Post date: [July 27, 2023, 8:54pm UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/29 "2023-07-27T20:54:41Z")

</div>

> [@jar1](#):
>
> [Matlab](https://www.mathworks.com/help/matlab/ref/switch.html)
> 
> ```julia
> switch n
> case -1
> disp('negative one')
> case 0
> disp('zero')
> case 1
> disp('positive one')
> otherwise
> disp('other value')
> end
> 
> ```
> 
> [MLStyle](https://thautwarm.github.io/MLStyle.jl/latest/syntax/pattern.html)
> 
> ```julia
> @match n begin
> -1 => display("negative one")
> 0 => display("zero")
> 1 => display("positive one")
> _ => display("other value")
> end
> 
> ```

The Fortran syntax is also not that bad:

```julia
select case (n)
  case (-1)
    print *, 'negative one'
  case (0)
    print *, 'zero'
  case (1)
    print *, 'positive one'
  case default
    print *, 'other value'
end select

```

---

<div class="post-metadata">

### Author: ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)
#### Post date: [July 27, 2023, 10:34pm UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/30 "2023-07-27T22:34:54Z")

</div>

Common Lisp has `case` and `typecase` which might be nicer when matching against types (as in this case):

```plaintext
(typecase error
     (simple-error "not so bad")
     (serious-condition "must leave now")
     (t "giving up on default))

```

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [July 31, 2023, 10:03pm UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/31 "2023-07-31T22:03:32Z")

</div>

As long as we’re debating syntax, I would offer something like

```julia
y = try
	sqrt(x)
catch e::DomainError
	zero(x)
catch e::Union{MethodError, AssertionError}
	println("unhelpful remark")
	rethrow(e)
#= implicit rethrow for non-caught types
catch e::Any
	rethrow(e)
=#
finally
	println("at least it's over")
end

```

The `catch` statements would be considered until the first matching signature. In fact, I might go so far as to just write this as `catch e isa DomainError` rather than `catch e::DomainError`. In either case, this would be equivalent to something like

```julia
y = try
	sqrt(x)
catch e
	if e isa DomainError
		oftype(x,NaN)
	elseif e isa Union{MethodError, AssertionError}
		println("unhelpful remark")
		rethrow(e)
	else # implicit rethrow for non-caught types
		rethrow(e)
	end
finally
	println("at least it's over")
end

```

although I suppose that isn’t so awful to write long-form already. How much is really saved?

This would be nice if the semantics were to choose the first applicable `catch`. But if we want the most specific `catch` to apply, then something looking like dispatch (e.g., `e::AssertionError -> println("AssertionError")` in a suggestion above) would be more appropriate. Although I don’t like that the example uses anonymous functions as it’s tedious to make multi-line expressions with them (and the anonymous function extended syntax `function (e::AssertionError)` gets weird because I don’t know whether people are suggesting to make these literal functions – can you `rethrow` from a child scope? If you want actual functions, just make a named function and call it from the `catch`).

To be honest, I rarely write `catch` to handle more than one specific error type (and just `rethrow` the rest) so I don’t know which (“first” or “best” or something else) might be more useful. How much do people nitpick around multiple specific error types in the wild? Enough that this is even useful?

---

<div class="post-metadata">

### Author: ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)
#### Post date: [August 1, 2023, 7:08am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/32 "2023-08-01T07:08:49Z")

</div>

> [@mikmoore](#):
>
> As long as we’re debating syntax, I would offer something

I don’t see how your suggestion is different from mine (your example makes a few details more explicit, but it seems to be the same otherwise), but as long as we’re on the same track, I’m happy with it.

> [@mikmoore](#):
>
> But if we want the most specific `catch` to apply, then something looking like dispatch

Yeah, I’m definitely voting on classic dispatch semantics, i.e., the most specific applies. The reason being, this is the natural way for Julia.

> [@mikmoore](#):
>
> can you `rethrow` from a child scope?

Apparently, you can, as long as the code is running within a catch block. I have tested this both in my initial example and when I experimented with the `@dispatch` macro above.

> [@mikmoore](#):
>
> To be honest, I rarely write `catch` to handle more than one specific error type (and just `rethrow` the rest) so I don’t know which (“first” or “best” or something else) might be more useful. How much do people nitpick around multiple specific error types in the wild? Enough that this is even useful?

Well, it has to be one way or the other, so again, I suggest use the one that better blends in with the rest of the language, so go for the best match.

My 2 cents, anyway.

---

<div class="post-metadata">

### Author: ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)
#### Post date: [August 1, 2023, 8:52am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/33 "2023-08-01T08:52:38Z")

</div>

I like the syntax you and @mikmoore proposed. I am thinking about the question of catching the first matching or the closest matching exception type.

It seems that catching the first matching is quite simple to implement: the new syntax would be just a syntactic sugar that would expand to the if-conditions as already shown in this topic. On the other hand, catching the closest matching exception type (as in method dispatching) sounds more challenging to implement (?).

With that in mind, catching the first match seems sufficient. I believe that the typical `try` would come with just a few `catch` blocks. I would even say that one often needs to handle just a single exception type. Moreover, the different `catch` blocks would be very close to each other (in terms of both the location in the source code and the program logic), which is not the case when dispatching methods. Overall, I don’t think that catching the first matching exception leaves too much burden to the programmer; the programmer just needs to catch the more specific types first (IF the types even share a parent).

---

<div class="post-metadata">

### Author: ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)
#### Post date: [August 4, 2023, 9:12am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/34 "2023-08-04T09:12:31Z")

</div>

> [@HanD](#):
>
> You’re perfectly right. How about this form then, to emphasize dispatch, but to reduce boilerplate?
> 
> ```julia
> try
> catch e
> @dispatch_error e begin
> e::AssertionError -> println("AssertionError")
> e::InexactError -> println("InexactError")
> end
> end
> 
> ```
> 
> **Update:** It doesn’t have to be called `@dispach_error`, it could be `@dispatch_lambda` or plain `@dispatch` as well, since there is no error specific stuff in it.
> 
> ```julia
> 
> ```

I published my implementation as a library on GitHub: [GitHub - dhanak/InlineDispatch.jl: A simple Julia module to perform dispatch on a value of an expression using the `@dispatch` macro.](https://github.com/dhanak/InlineDispatch.jl)

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [August 4, 2023, 3:14pm UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/35 "2023-08-04T15:14:35Z")

</div>

My main takeaway from this thread is that we should not implement the multiple catch block syntax as initially proposed because it is ambiguous. It is unclear if we want to do matching or dispatch.

> [@barucden](#):
>
> On the other hand, catching the closest matching exception type (as in method dispatching) sounds more challenging to implement (?).

We literally just implemented dispatching in this thread. It was not too difficult.

> [@mikmoore](#):
>
> Although I don’t like that the example uses anonymous functions as it’s tedious to make multi-line expressions with them

You can use begin or let blocks for multiline expressions.

```julia
e::AssertionError -> begin
    # first lone
    # second line
    # third line
end

```

That said we probably should allow for the other anonymous function forms as well.

---

<div class="post-metadata">

### Author: ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)
#### Post date: [August 14, 2023, 6:34am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/36 "2023-08-14T06:34:55Z")

</div>

…and `InlineDispatch` is now in the General registry. Happy dispatching!

---

<div class="post-metadata">

### Author: ![anon91151494](https://avatars.discourse-cdn.com/v4/letter/a/838e76/32.png) [@anon91151494](https://discourse.julialang.org/u/anon91151494)
#### Post date: [October 1, 2024, 9:21am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/37 "2024-10-01T09:21:51Z")

</div>

I would like to add some additional support to this proposal.

> [@HanD](#):
>
> ```julia
> try
> # body with potential exceptions
> catch e::AssertionError
> # handle assertion errors here
> catch ::InexactError # note the missing variable
> # handle conversion errors here
> end
> 
> ```

There are a few reasons to implement this.

1. This syntax would allow for a removal of 1 additional level of indentation. (No indentation level required for an extra `if` construct to check the error type.) This is not a triviality - it makes code easier to read.
2. It results in a more concise syntax. In my experience less typing, or less verbose languages, result in higher levels of productivity. This is simply because the expressiveness of the language is greater and it takes less time to write the code. Again, not a triviality.
3. Most other languages support it and therefore if Julia supported such a syntax it would be more closely aligned with what most developers expect to write. It doesn’t necessarily matter if Julia differs from other languages, but in this particular case the additional required `if` statement is a bit awkward or jarring compared to other languages which have the more succinct form.

However, I also recognized that there may be higher priority tasks or lower hanging fruit for the language developers.

---

<div class="post-metadata">

### Author: ![anon91151494](https://avatars.discourse-cdn.com/v4/letter/a/838e76/32.png) [@anon91151494](https://discourse.julialang.org/u/anon91151494)
#### Post date: [October 1, 2024, 9:23am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/38 "2024-10-01T09:23:30Z")

</div>

> [@stevengj](#):
>
> TLDR: it was rejected in 2012 since `rethrow()` is semantically sufficient (this is just syntactic sugar)

I don’t understand this - can someone explain with a short example code? I haven’t understood the point being made here.

---

<div class="post-metadata">

### Author: ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)
#### Post date: [October 4, 2024, 9:33am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/39 "2024-10-04T09:33:52Z")

</div>

27 posts were split to a new topic: [Use exceptions vs other patterns?](https://discourse.julialang.org/t/use-exceptions-vs-other-patterns/120900)

---

<div class="post-metadata">

### Author: ![anon91151494](https://avatars.discourse-cdn.com/v4/letter/a/838e76/32.png) [@anon91151494](https://discourse.julialang.org/u/anon91151494)
#### Post date: [October 4, 2024, 11:28am UTC](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840/40 "2024-10-04T11:28:20Z")

</div>

> [@jar1](#):
>
> I am opposed to this change because it encourages the use of exceptions for expected errors. IMO exceptions should be used for unexpected errors, and another system should be introduced for producing and handling failure values. Python uses exceptions for control flow; I don’t think Julia should.

Now I understand the point trying to be made here I realize that imo this makes no sense.

The claim here is that because _some_ authors of Python code use of exceptions wherever possible (something which is already bad design practice) **and** because _specifically in the case of_ _ **Python** _ there is no _performance penalty_ for the use of exceptions, therefore Julia should not support them.

This doesn’t apply to any other language, other than Python.

To say Julia shouldn’t support something that most other languages support because some Python programmers might bring their bad habits with them really doesn’t make a lot of sense imo.

[Previous page](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840.md?page=1)

[Next page](https://discourse.julialang.org/t/new-syntax-suggestion-catch-with-type-specs/101840.md?page=3)
