New syntax suggestion: catch with type specs

Here’s the prototype.

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> 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> @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?

8 Likes