Julia: Overloading MethodErrors for certain method signatures

Created on 3 Feb 2020  路  2Comments  路  Source: JuliaLang/julia

In response to this thread https://discourse.julialang.org/t/idea-julia-lite-or-juliette/34076/60 I think it could be valuable to add error messages for some errors that appear with high frequency, but which are not easily understood just from the MethodError they throw.

Example:

rand(5) + 3
ERROR: MethodError: no method matching +(::Array{Float64,1}, ::Int64)
Closest candidates are:
  +(::Any, ::Any, ::Any, ::Any...) at operators.jl:529
  +(::Complex{Bool}, ::Real) at complex.jl:297
  +(::Missing, ::Number) at missing.jl:115
  ...
Stacktrace:
 [1] top-level scope at REPL[123]:1

We know that this is something tons of people try when they start using the language coming over from Python, R, Matlab, etc. So it would be beneficial to teach them about dot broadcasting right here, in the error message. One could overload addition to remedy this:

function Base.:+(arr::AbstractArray{<:Number}, x::Number)
    error("""No method matching +(::$(typeof(arr)), ::$(typeof(x))).
    For element-wise addition, try dot-call broadcasting syntax: arr .+ x""")

This would result in:

julia> rand(5) + 3
ERROR: No method matching +(::Array{Float64,1}, ::Int64).
For element-wise addition, try dot-call broadcasting syntax: arr .+ x
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] +(::Array{Float64,1}, ::Int64) at ./REPL[1]:1
 [3] top-level scope at REPL[2]:1

I don't think actually overloading all these methods directly is the right way to go. But would it be possible to overload only the specific MethodError for this kind of problem? Are MethodErrors typed in a way that one could dispatch on the type of error and give helpful messages in well-known cases like this, Array of Numbers plus / times / minus / etc. a scalar? I think this could be a highly effective mechanism in other cases as well.

good first issue

Most helpful comment

Thank you for pointing me in the right direction, I've submitted a PR with a potential improvement here https://github.com/JuliaLang/julia/pull/34642

All 2 comments

I think you've hit on the right approach. Here's how it can be fixed:

julia> a = [1,2,3];

julia> err = try
       a + 1
       catch e
       e
       end
MethodError(+, ([1, 2, 3], 1), 0x0000000000006899)

julia> @edit showerror(IOBuffer(), err)

As you'll discover, the MethodError captures the function and the arguments, so it should be reasonably straightforward.

Thank you for pointing me in the right direction, I've submitted a PR with a potential improvement here https://github.com/JuliaLang/julia/pull/34642

Was this page helpful?
0 / 5 - 0 ratings

Related issues

StefanKarpinski picture StefanKarpinski  路  141Comments

shelakel picture shelakel  路  232Comments

tknopp picture tknopp  路  171Comments

StefanKarpinski picture StefanKarpinski  路  138Comments

jiahao picture jiahao  路  417Comments