I agree that this example is not explained well in the manual. At least I did not find a very clear explanation by searching briefly.
The important thing to realize is that + does not universally denote the same function. Function names are no different than variable names - they share the same namespace if you wish. For example you could extend your code with
let - = +
println(a-b)
end
and it would just work and do the same as your a+b.
What does that mean for your example?
- When you want to add a method to
+you really mean+fromBase, which needs to be written asBase.:+in a function definition (I think this syntax is explained somewhere but I didn’t find it quickly - somewhat confusingly when importing something bothimport Base.+andimport Base.:+work). - To add a method to an existing function from a package you are
using, you need to use its full name in the definitionfunction Base.:+(...)asfunction +(...)would introduce a new local function named+and shadowBase.:+in the local scope, meaning you could not add things anymore. - On the other hand, if you
importthe other module, thenfunction +(...)would NOT define a new function and just add a new method to the existing function! This a crucial difference betweenusingandimport, that’s explained in the FAQ but perhaps could use an example for illustration. - So generally you need to either
importmodules to add methods to their functions or use the long form of the method’s name (likeModule.function) in the function definition. I personally would always recommend the latter as that makes it more clear to the reader that an external function is extended (imo). - You don’t need to (re)export
+fromMyModuleas it is identical withBase.:+.
So you can simplify your code to:
module MyModule
export Point
struct Point{T<:Real}
x::T
y::T
end
function Base.:+(a::Point, b::Point) # no need to repeat the type parameter if unused
return Point(a.x + b.x, a.y + b.y)
end
end
using .MyModule
a = Point(1.0, 2.0)
b = Point(3.0, 3.0)
print(a+b)