Good template for defining a custom type with an addition method

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?

  1. When you want to add a method to + you really mean + from Base, which needs to be written as Base.:+ in a function definition (I think this syntax is explained somewhere but I didn’t find it quickly - somewhat confusingly when importing something both import Base.+ and import Base.:+ work).
  2. To add a method to an existing function from a package you are using, you need to use its full name in the definition function Base.:+(...) as function +(...) would introduce a new local function named + and shadow Base.:+ in the local scope, meaning you could not add things anymore.
  3. On the other hand, if you import the other module, then function +(...) would NOT define a new function and just add a new method to the existing function! This a crucial difference between using and import, that’s explained in the FAQ but perhaps could use an example for illustration.
  4. So generally you need to either import modules to add methods to their functions or use the long form of the method’s name (like Module.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).
  5. You don’t need to (re)export + from MyModule as it is identical with Base.:+.

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)
4 Likes