Is there a convenient way to avoid the error message when using two modules which export a function the same name?
Scenario is that package A depends on B and C. C just added a function which collides with one in B. Both C and B export alot of things which are used in A.
Is there an easier way than manually importing/qualifying everything out of B and/or C which A makes use of? Something like “use all but this from B”.
Out of curiosity: what were the function names and where the functions take at least one argument which was defined in the package? Were the functions conceptually very close in what they expected and returned, or so fundamentally different you would never mix them up?
To satisfy your curiosity then : Name is flatten and in one package it turns an ND array into a matrix and in the other it turns a graph into an array of its vertices.
Oh well, I guess I just learned a valuable lesson about encapsulation and it does not cost anything more than a major revision number and the inconvenience of having to always import stuff from B and C when using A
About that using warning … I probably misunderstand, but this does not produce a warning:
# test1.jl
module B
export foo
foo() = println("B");
end
module C
export foo
foo() = println("C");
end
module A
using ..B, ..C
B.foo()
C.foo()
end
using .A
and then on the REPL
julia> include("../scratch/test1.jl")
B
C
Sorry if I misunderstand the kind of warning you are talking about.
It seems like the warning (which indeed is very helpful and potentially sanity preseving) is only produced when an actual unqualified call to the function is done in the module:
module B
export foo
foo() = println("B");
end
module C
export foo
foo() = println("C");
end
module A
using ..B, ..C
B.foo()
C.foo()
foo()
end
using .A
REPL:
julia> include("footest.jl")
B
C
WARNING: both C and B export "foo"; uses of it in module A must be qualified
ERROR: LoadError: UndefVarError: foo not defined
I could have sworn I had qualified all usage of flatten in A and I still got the warning when using it. I will double check it again but I think you just saved me one internet bit for a major revision number
Ok, I have narrowed it down to this (it didn’t take me 2 hours, I was watching TV with the wife until she got tired, I promise):
#footest.jl
module B
export foo
foo() = println("B");
end
module C
export foo
foo() = println("C");
end
module A
using Reexport
@reexport using ..B
@reexport using ..C
import InteractiveUtils: subtypes
subtypes(Integer)
B.foo()
C.foo()
end
using .A
julia> include("footest.jl")
WARNING: both C and B export "foo"; uses of it in module A must be qualified
B
C
Next stop is to see if there is some kind of witchcraft going on in Reexport could explain this…
module B
export foo
foo() = println("B");
end
module C
export foo
foo() = println("C");
end
module A
using Reexport
@reexport using ..B
@reexport using ..C
module AA
export T, TT
abstract type T end
struct TT <: T end
end
@reexport using .AA
import InteractiveUtils: subtypes
subtypes(AA, T)
end
using .A
Types TT and T where originally defined inside A, but that caused subtypes to trigger the warning when called. Putting them inside an internal module which is reexported seemed to avoid the issue.
Reexport was innocent here. Replacing it with explict exports (without the workaround) produced the same behaviour.
module B
export foo
foo() = println("B");
end
module C
export foo
foo() = println("C");
end
module A
using Reexport
using ..B
using ..C
abstract type T end
struct TT <: T end
import InteractiveUtils: subtypes
@show subtypes(A, T)
@reexport using ..B
@reexport using ..C
end
using .A