Functions inside of struct block

I noticed this code in Pkg, and the the utility of the copy function inside the struct block eludes me even though it’s commented:

struct VersionSet
    intervals::Vector{VersionInterval}
    VersionSet(intervals::Vector{VersionInterval}) = new(normalize!(intervals))
    # copy is defined inside the struct block to call `new` directly
    # without going through `normalize!`
    Base.copy(vset::VersionSet) = new(copy(vset.intervals))
end

How is copy ever used? More generally, what is the scope of functions defined in the struct block?

It doesn’t define a new function so there isn’t really any scope to talk about (except the one of the original function).

To clarify Kristoffer’s comment, that line of code extends the same Base.copy as if it were defined outside the struct. The reason it is defined inside is that it calls new, which is only accessible inside the scope of the struct definition.

The “function” new is ever only accessible from inside a struct definition, and directly constructs an instance of VersionSet, avoiding the constructor (which is defined here on the third line). That constructor does some work to preserve an invariant across all instances of VersionSet, but since the purpose of copy is to duplicate an existing pre-constructed VersionSet, we know that work can be avoided.

With a struct like this, where the inner constructor always does some work, the only way forward is to call new directly, which you can only do from inside the scope of a struct definition, which is why the extension of Base.copy ended up being put there – to have access to new.

9 Likes

Ah I see now, thanks for the great explanation!

1 Like