Question on Defining Functions Inside Structs

I noticed in this video here that several constructors for the struct are defined inside the struct block itself. I’ve not personally done this to date, it just didn’t occur to me. I’ve always defined alternate constructors outside the struct block.

Is there any particular reason to do this or not do this (define outer constructors inside the struct block)?

This section of the docs is quite helpful for this.

There are two use cases which cannot be done by outside outer constructors:

While outer constructor methods succeed in addressing the problem of providing additional convenience methods for constructing objects, they fail to address the other two use cases mentioned in the introduction of this chapter: enforcing invariants, and allowing construction of self-referential objects. For these problems, one needs inner constructor methods.

I’ve read the section in the manual on inner and outer constructors several times but its possible I still missed it - but if you look at the video that isn’t what is going on (I don’t think).

There is no use of the keyword new. He is defining outer constructors inside the struct block. I’m asking if that matters or means anything. Is there any reason to do that versus defining them outside the struct block.

Outside of being able to enforce invariants and self-referential objects. There is no difference between internal methods and external. There is a disadvantage tho, external methods can easily be redefined, while internal ones can’t

One example:

julia> struct A
           x
           A(x) = new(2*x) # ambiguous, overwrites the default A(x)
       end

julia> A(x,y) = A(x+y) # outer constructor, not ambiguous
A

julia> A(1)
A(2)

julia> A(1,2)
A(6)

julia> A(x) = A(3*x) # this will be ambiguous, self-referential
A

julia> A(1)
ERROR: StackOverflowError:
Stacktrace:
 [1] A(x::Int64) (repeats 79984 times)
   @ Main ./REPL[8]:1

thus, one of the uses is to avoid self-referential constructors, when the parameters of the method are the same as that of the default constructor.

I am not referring to or asking about the distinction between inner and outer constructors. If you watch the video (the link contains the time where it occurs) you’ll see he’s defining outer constructors inside the struct block. I’m asking if there is anything special or reason to do that as opposed to defining them outside the struct block.

I say they are outer constructors because there is no use of the keyword new which would indicate to me it is an inner constructor. Maybe that’s what I have misunderstood.

I think you might have misread it


Those are all outer constructors, it’s just that he put them all inside a begin end block. IIRC he has to do that because of pluto.

3 Likes

You can create inner constructors that could be written as well as outer constructors:

julia> struct A
           x
           A(x,y) = new(x + y)
       end

julia> A(1,2)
A(3)

There is no difference relative to defining it outside with A(x,y) = A(x + y). But it is not the recommended pattern:

It is good practice to provide as few inner constructor methods as possible: only those taking all arguments explicitly and enforcing essential error checking and transformation. Additional convenience constructor methods, supplying default values or auxiliary transformations, should be provided as outer constructors that call the inner constructors to do the heavy lifting. This separation is typically quite natural.

1 Like

ahhh, you are right! I see the reason for my confusion now. Thank you!

2 Likes