Reputation: 655
I saw this construction in rationals.jl, and I am trying to understand it. I can write
struct Bar
y
global func(x) = new(x)
end
Then if I try:
a = Bar()
I get an error. It is like func
is now an inner constructor. And I can actually use it by writing:
a = func(2)
If I remove the keyword global
, I can't use this inner constructor anymore. What is going on? Why is global
there, and could I use the inner constructor somehow without it (perhaps by qualifying the name)?
How can the inner constructor have a different name than the struct itself? What, in fact, is an inner constructor?
Upvotes: 2
Views: 205
Reputation: 20970
An inner constructor is a method of the struct type (i.e., (::Type{Bar})(...)
which has access to new
. You can put arbitrary method definitions inside a struct -- there is no technical requirement to only have inner constructors -- but this is only useful in rare cases.
This is a rare case that the manual doesn't even cover explicitely (and I long didn't know was legal at all). In my understanding, two rules apply:
new
.If any inner constructor method is defined, no default constructor method is provided: it is presumed that you have supplied yourself with all the inner constructors you need.
However, nothing requires the inner constructor to be a method of the struct type! Instead you may actually define arbitrary methods.
And then, scoping applies. With a "regular" inner constructor, what you get is a method for Type{Bar}
. This requires no global
, as the type is present in outer scope.
In your case, without the global
, func
is local and so there is no constructor accessible at all outside the struct definition. This makes little sense. The global
function definition is something that can be useful in rare cases when you want to prevent direct construction of values of you type, but only allow conversion. I have seen this kind of pattern:
struct Baz
Base.reinterpret(::Type{Baz}, ...) = new(...)
end
This adds a (globally available) method to reinterpret
, the only entry point to constructing Baz
es. Putting it inside the struct is necessary, as at some place you need to create the object and thus require access to new
.
Upvotes: 4