I think we can again learn from C++'s ADL approach here. The following is valid in C++:
namespace A {
struct MyType{ };
template <typename T>
auto f(MyType, T) {return 1;};
}
// note: no using namespace A!
int main() {
A::MyType m;
f(m, 2);
}
That is, you can have generic (templated) functions that are still found correctly using argument-dependent lookup, by virtue of the fact that at least one of the arguments is specifically of a type defined in the same namespace (module in Julia) in which the function is defined.
If two user modules A
and B
define a function foo(::Number)
, then of course there is ambiguity when foo
is used in a third package that uses both A
and B
, but argument-dependent lookup would not apply because Number
is not defined in A
or B
.
A sketch of what this could like in Julia:
module A
struct AA end
foo(::AA) = :A
bar(::Number, ::AA) = :A
baz(::Number) = :A
end
module B
struct BB end
foo(::BB) = :B
bar(::Number, ::BB) = :B
baz(::Number) = :B
end
module C
import A, B # import, not using!
foo(A.AA()) # fine, calls foo in A
foo(B.BB()) # fine, calls foo in B
bar(A.AA()) # fine, calls bar in A
bar(B.BB()) # fine, calls bar in B
baz(1.0) # bad: ADL not triggered, so baz not defined.
end