Hello, I have the following situation which I did not expected: defining a fucntion with the same name but different signature in two modules like this:
## Module RawTables
function save(T::RawTable, name_pref::String)
...
end
## Module RawPlots
function save(T::RawPlot, name_pref::String)
...
end
and using them together results in
WARNING: both RawPlots and RawTables export "save"; uses of it in module Main must be qualified
I thought multiple dispatch is exactly good in being able to resolve this issue for me? Basically it is only function overloading in this case and there simply cannot be any problems about what method to call.
What is happening here and how can I resolve this? Thanks
Just because two generic function (which is the container of the methods) have the same name, does not mean that they are the same object (you can check this with ===). You need to extend the generic function defined in one module in the other; just like with Base functions:
julia> module A
export f
f() = 1
end
Main.A
julia> module B
using ..A
A.f(x) = 2
end
Main.B
julia> using .A
julia> f()
1
julia> f(1)
2
Thanks. But this implies that the modules have to know about each other, which is not useful for anything else. And I have to specify the hierarchy which module extends the other one?
Maybe there can be some check whether the name exists and extend it or otherwise create a new object?
I mean, e. g. in this example save is a very common name but yet it is not in Base. Does this mean, that everyone needs to know about evry other module which possibly also uses save and extend it?
No; just that you have to know about another module if you want to extend methods of that specific module when developing a module. Otherwise you just have to specify which modules version you intended to use when actually using both modules at the same time.
Thank you for the link. Well, I have looked through it and I clearly would vote for a possibility to have common function names from different modules to work together smoothly without the need to import them or state the module explicitly
They already do; if you only import one of them, that warning is not going to show up. It shows up in the example provided by @mauro3 because they’re both contained in the top level scope Main and are referencing each other and are thus loaded by default in the REPL.
You only have to do this when developing a module and explicitly want to add to that modules functions method tables. You are not required to qualify every module that might potentially have a save function.
This is exactly the problem I have. Neither do I extend the save behavior nor do I want to specify the module name because I call the save function with a type which clearly can decide the right version of the function for me.
In my option this is a very clear case of “do the same thing” bit still belong to different modules.
I can understand that this can lead to errors on the big scale but for some very common words which are not in Base I really would like to see a way to do this. For convenience, not because it is logically the best option for a programming language and all this discussion about “doing the same thing”.
Dispatching to a specific method of the save function based on the input types is exactly what extending the function is. And knowing what save means is necessary in order to write generic code. If everyone has their own version of push! with arbitrary meaning, that means that whenever you see some code like
function g(x)
for i in 1:100
push!(g, i)
end
end
you have no idea what the purpose of it is.
Now you can just:
help?> push!
search: push! pushfirst! pushdisplay
push!(collection, items...) -> collection
Insert one or more items at the end of collection.
If you read through that thread, you will notice some workarounds along the lines of
import A # has f
import B # has f
f(x::SomeType) = A.f(x) # specifically for SomeType
f(x) = B.f(x) # fallback
and variations on this theme.
In general: Julia, like most contemporary generic programming languages, is very careful about namespace management. This may seem inconvenient in some cases, but I suppose that after writing a few 10⁴ LOC you will see its value.