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
import
the other module, thenfunction +(...)
would NOT define a new function and just add a new method to the existing function! This a crucial difference betweenusing
andimport
, that’s explained in the FAQ but perhaps could use an example for illustration. - So generally you need to either
import
modules 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
+
fromMyModule
as 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)