Open ivarne opened 10 years ago
This makes a lot of sense. Could it also be used for depreciated functions? Right now I think they're still implemented but throw an exception or warning.
It should also be available for modules, so packages can point out the replacements for old functions.
In fact if all modules could implement deliberatly_unimplemented_methods
someone could come along and write for example a "MatlabHelper" package that just defined lots of matlab functions that are not available in Julia with advice on equivalents.
Deprecated functions usually just prints a warning, and then perform what the old function was supposed to do. There might be something said for keeping a warning here, when the deprecation is fully removed though.
It should definitely be extensible for modules. Would it be enough to just document how to push!
more suggestions onto the array?
IMO encountering minor differences in surface syntax or function names is entirely natural when learning a new language. I am not sure that hints like this belong in the language proper, especially since there are zillion other languages out there from which users can come to Julia, and it is nearly impossible to provide hints to everyone. For example, a former R user is likely to encounter difficulties different from someone coming from Python, etc.
Wiki pages which enumerate differences between Julia and another languages would be more useful IMO. Eg similar to the table at the end of http://norvig.com/python-lisp.html
+1 for this general approach.
I love the idea of deliberately unimplemented methods. It would make the information from applicable
and method_exists
far more useful.
@tpapp It depends on how you look at it, but I would not consider replutils.jl
part of the Julia language. Currently lots of tooling has found its way into the Base
folder, and there is an open issue about cleaning it up. It is somewhat stuck because of technical limitations (system image) and a desire to have everybody use pretty much the same system when debugging issues.
Teaching language philosophy and differences is definitely not the target of this feature, but I don't think there are many functions where former R and Python users have different intentions when trying to call a undefined method in Julia.
It is also possible to save some memory by not lazy loading this list, so I don't think there are going to be problems when 10 languages add their entire standard library with suggestions for Julia alternaltives.
I'm not sure this needs to be extensible from the start, but making this extensible seems like another case of #3988 (see also discussion in #5572).
It should definitely be extensible for modules. Would it be enough to just document how to push! more suggestions onto the array?
Sounds fine to me.
@tpapp, I see what you mean, and I guess this is the difference between the purist and the popularist. Personally I want Julia to be popular and I think smoothing the initial "bump" of changing language is one of the most important ways of doing this.
I gave an introductory presentation on Julia the other day and one of the thinks people liked most was what they got "in the box", eg.;
Strictly none of these are "part of the language" but it's convenient for them to come with it.
Remember, the biggest reason (by far) that people use matlab is the IDE that comes with the language, not the language.
Strictly none of these are "part of the language" but it's convenient for them to come with it.
One of the important things about shipping with something is that it tends to actually work, whereas add-ons have a much lower rate of working.
I really like the idea of having hints, but it seems a bit messy to define these values directly in the code. Perhaps there should be a fixture file (.method_hints
?) that defines a list of these methods:
Each row of the .method_hints
file would contain a tab-delimited signature of the method to relay the error:
For example:
:+ (String, String) "Use * for string concatenation"
:max (AbstractArray,) "Use maximum to find the largest element in an array"
@Aerlinger That saves some typing, but I don't think a special purpose parser makes things less messy. It will also be a new syntax to learn (even though it is intuitive). Julia code can also be placed in a separate file and loaded on demand.
While we wait for someone to implement something like this, we should probably collect more examples on commonly missing methods. The format you use, can be treated as a vote.
Per #7686, it would also be great to print "closest" matching methods for general MethodErrors, although defining the metric is going to be difficult.
This is how I think it would be ideal to display:
f(x::Float64, y::Float64) = println("ff")
f(x::Int, y::Int) = println("ii")
f(x::Float64, y::Int) = println("fi")
f(1, 1.0)
ERROR: `f` has no method matching f(::Int64, ::Float64)
Closest candidates are:
f(::Float64, ::Float64)
^~~~~~~~~
f(::Int, ::Int)
^~~~~
f(::Float64, ::Int)
^~~~~~~~~ ^~~~~
These underlines should indicate which arguments don't match.
Even better would be if this utilizes colored output: The wrong types are printed red and the underlining ^~~~
can be removed.
I like @jhasse suggestion
I suspect that this might cause more daunting messages for methods that are heavily overloaded.
Consider:
type A end
A() + A()
This could be equally distant to all methods of +
. Then this would produce a miles long list of things that virtually enumerate all 125 methods of +
(probably many more if other packages are being used).
Maybe remove all candidates where no arguments match at all? E. g. in my previous example:
f(1, 1.0)
ERROR: `f` has no method matching f(::Int64, ::Float64)
Closest candidates are:
f(::Float64, ::Float64)
^~~~~~~~~
f(::Int, ::Int)
^~~~~
Then your example would result in no list, but A() + 0
would have one. This would still be rather long, but I think that is wanted isn't it? Or the list could be truncated after 5 elements or so.
That would never print suggestions for functions with fewer than two arguments – which might be ok. This is also pretty non-trivial to implement, but if you want to have a crack at it, please feel free. This would be awesome to have.
Suggesting functions with different type signatures will not help in case of "a" + "b"
. Only the suggestion of a different function will help. I do not think that the correct suggestion can be found in general. A correct suggestion has to know, that the person has a Java background. But how about "a" . "b"
? How to know, that this is a Perl guy? And how about 'a' || 'b'
?
@ceving I don't understand what will not help.
The suggestion in this issue is to print helpful messages together with MethodError, when we see cases where we (think we) know what the user wants to do. The message might be anything, and will certainly often suggest different functions (actually both my examples suggest to change function (+
-> *
and max
-> maximum
))
We know many programmers don't read the full manual before starting to program in Julia, and if we manage to save them of a few searches to figure out our api, that would save them a lot of time.
If a common language defines something similar to +(::String,::String)
to mean something else, we can suggest the proper way to do that too.
deliberately_unimplemented_methods = Dict( :+ => ((String, String), "Use * for string concatenation"), :max => ((AbstractArray,), "Use maximum to find the largest element in an array") )
showerror
function to use this tablefunction Base.showerror(io::IO, err::MethodError)
for (method, (argtypes, suggestion)) in deliberately_unimplemented_methods
if err.f == method && err.types == argtypes
println(io, "MethodError: $(method)$(argtypes) is not implemented. $suggestion")
return
end
end
# Default behavior
Base.showerror(io, err)
end
try "Hello" + "World" # This will raise a MethodError catch e println(e) end
try max([1, 2, 3]) # This will raise a MethodError catch e println(e) end
One of the first problems you stumble upon when learning Julia, is the
MethodError
. When using the standard library, the reason is usually that you are doing something wrong, but the only thing the users sees isERROR: no method +(ASCIIString, ASCIIString)
. It would be very nice if the user would get a string with alternative suggestions.Currently Exceptions are printed with the help of
showerror(io::IO, err::MethodError)
in replutil.jlWe could have something like a table for lookup:
, but maybe we can find a better solution that also captures varargs functions.