Cannot find overloaded method

The OP had a simple question: -Why doesn’t this implementation work?

You are really taking this ball and running with it. If you don’t want to take the OP at face value, maybe ask what the intention was.

1 Like

Wow, thanks a lot for the numerous replies! I marked a solution, which is the code that actually fixes the MethodError in my original post without changing behaviour. Unfortunately, it’s not possible to mark several solutions, but many comments were useful for the understanding.

Now I see that indeed a more specific replace method is defined in (surprisingly!) set.jl in base julia. It explicitly throws a methoderror, and that’s why the resulting error message is extremely confusing: says that the method is not found, and lists this very method below.

As for the desired behaviour and replacement order - it would be best if the replacements were “simultaneous” as described in this thread above. My implementation makes replacements one-by-one just because it is the simplest possible implementation, and in actual usage I typically don’t care about the order: replacements are not ambigous. It’s just really convenient to write replace(str, a => b, c => d, e => f, g => h) - compare to replace(replace(replace(replace(str), a => b), c => d), e => f), g => h).

2 Likes

This is an alternative. A few more characters but no piracy.

foldl(replace, [str, a => b, c => d, e => f, g => h])
4 Likes

That’s indeed a shorter version - so the definition with for loop can be replaced with:

Base.replace(str::AbstractString, old_new1::Pair, old_new::Pair{String, String}...) = foldl(replace, [str, old_new1, old_new...])

But I would still find replace(x, a => b, c => d, ...) better at least for interactive usage:

  • Extending a single replacement replace(x, a => b) with the second one is easy: just add , c => d.
  • Intent is clear from the code: perform multiple replacements. No need to remember the fold-replace-str combination and order.

I don’t see anything wrong in type piracy per se. E.g., I’ve added the first(vec, n) and last(vec, n) methods in my personal utilities package more than a year ago and been using them just fine. When julia 1.6 will get released (with the corresponding PR) I will just remove those two methods from my package and that’s it. And there are many more cases, e.g. deg2rad(::Missing), lowercase(s::Symbol), etc - everything works fine, I had no issues with those.

In your personal utility package you are of course free to do what you like, but it is still bad style in packages intended for general use.

Because of this, I think it is best if Julia programmers just stay away from type piracy (unless there is a compelling reason) — it is just easier to make this a habit in general and not think about it any more.

1 Like

It seems to me many extensions of methods/ new methods which found their way in base started
with extensions in packages — what you call piracy. So you better find the right equilibrium between stifling progress by forbidding all piracy and sowing chaos with widespread piracy.

I fully agree with you that piracy should be kept in personal packages or packages that explicitly state that they perform said piracy (automatic detection possible?). But to completely stay away from it seems too strict for me.

I think you misunderstand how the Julia package ecosystem works. Currently, the General registry does not forbid type piracy, it is just a style recommendation. You are still free to do it. There is no type piracy police.

I am not sure what you mean here, but in any case extensions rarely need to pirate Base methods. Packages that really need to do type piracy are usually very explicit about it to warn users, eg

1 Like

Just saw it in the Julia 1.7 news:

replace(::String) now accepts multiple patterns, which will be applied left-to-right simultaneously

This means there will be no need for the replace method discussed in this thread, it will just work with Base!

julia> replace("abc", "a" => "x", "b" => "y")
"xyc"

(:

3 Likes