JuliaLang/julia

Improving MethodError message for anonymous functions

Open

#56 325 ouverte le 25 oct. 2024

Voir sur GitHub
 (7 commentaires) (6 réactions) (0 assignés)Julia (5 773 forks)batch import
error messagesgood first issue

Métriques du dépôt

Stars
 (48 709 stars)
Métriques de merge PR
 (Merge moyen 23j 11h) (145 PRs mergées en 30 j)

Description

Context: improving error experience for beginner Julia programmers.

In this example, you get a MethodError for your anonymous method (::var"#3#4"):

julia> vals = [5,6,10,20];

julia> accumulate(vals; init=0) do (old, new)
           old + new
       end
ERROR: MethodError: no method matching (::var"#3#4")(::Int64, ::Int64)
The function `#3` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  (::var"#3#4")(::Any)
   @ Main REPL[2]:2

Stacktrace:
 [1] _accumulate!(op::var"#3#4", B::Vector{Union{}}, A::Vector{Int64}, dims::Nothing, init::Some{Int64})
   @ Base ./accumulate.jl:368
 [2] accumulate!(op::Function, B::Vector{Union{}}, A::Vector{Int64}; dims::Nothing, kw::@Kwargs{init::Int64})
   @ Base ./accumulate.jl:350
 [3] accumulate(op::Function, A::Vector{Int64}; dims::Nothing, kw::@Kwargs{init::Int64})
   @ Base ./accumulate.jl:291
 [4] top-level scope
   @ REPL[2]:1

The problem is that my do syntax used (old, new) (a single tuple argument) instead of old, new (two integer arguments):

julia> accumulate(vals; init=0) do old, new
           old + new
       end
4-element Vector{Int64}:
  5
 11
 21
 41

But the error is difficult to understand!

Ideas

I have seen this pattern more often (MethodError on an anonymous function that I defined), and I think we could make meaningful improvements to this error message! Ideas:

  1. Say "anonymous function": We can communicate better that it's about an "anonymous function". The name var"#3#4" is not so useful for beginners. (In the case of a do-block, it might even be non-obvious that you wrote a function.)
  2. Simplify "Closest candidates": Anonymous functions can only have one method (right?). So instead of showing "Closest candidates", the error can be stated in a simpler way:
The anonymous function has signature:
   (::Any)
but it was called with types:
   (::Int64, ::Int64)
  1. Number of arguments: the function was called with 2 arguments, but no method accepts that. When dispatch fails because of the number of arguments, I think this is the most helpful bit of debugging info available (like a sanity check), and we could say this explicitly in the error. It could be phrased as advice (when the situation is simple enough):
Tip: The function was called with 2 arguments, but it only accepts 1 argument.

Guide contributeur