After a couple of months of using Julia, I’m still a little confused about how methods interact with packages/namespaces. That is, situations where a package adds additional methods to a function originally defined in another package.
If I have a package A that defines (and exports) func and another package B that defines additional methods for func, it seems like doing using A and using B in the REPL, I get the combined methods from A and B. This does not seem to depend on whether B also exports func. Is that officially how things are supposed to work: If I’m using A, do all methods for func defined in other packages that I might use directly or indirectly get merged in automatically? With “indirect” I mean if I’m using C and the package C has a uses B, do I get the methods that B defines for A.func automatically?
Is there any way to use (parts of) B but not use the methods that B defines for A.func? One might expect that if I do using A and using B: func2 (where func2 is some unrelated function), I wouldn’t get B’s method for A.func, but in fact I do.
Second, while an explicit export of func in B doesn’t seem to affect whether B’s method for A.func gets used or not, it does seem to have some effect when I’m not directly using the package A that originally defines func. If my package B looks like this:
module B
import A
A.func(i::Int) = i
end
and I’m only using B in the REPL but not using A, then neither func not B.func is available. However, if my package B reads
module B
import A: func
func(i::Int) = i
end
then using B (without using A) in the REPL does give me access to B.func, and B.func includes both the methods from A and from B.
If I further export func, that is,
module B
import A: func
export func
func(i::Int) = i
end
then using B in the REPL (again without using A), gives me access to both func and B.func, again using the methods from both A and B.
Also, in that case, if I’m both using A and using B explicitly in the REPL, I can address func as func, A.func, or B.func, with all three being completely equivalent.
Lastly, if I define the package B as
module B
import A
export func
A.func(i::Int) = i
end
I don’t get any complaints from Julia, but the REPL autocompletion thinks that both func and B.func exist, but then gives me an UndefVarError: func not defined.
This last one seems like a bug. As for all the previous examples, they all seem okay, but I can’t say that I have a good mental model for why exactly they behave the way they do. Is there one?