Struct default value in constructor

I need the following struct:

struct Foo
    bar
    baz
    qux = bar + baz

The problem is that in constructor I need to set the value of “qux”, and I want the value only depend on “bar” and “baz”.

How can instantiate a struct only setting the value of some of it’s fields?

Thanks.

I think an inner constructor might be what you want here.

2 Likes
struct Foo
    bar
    baz
    qux
    Foo(bar, baz, qux) = (bar+baz) == qux ? error("qux must be the sum of bar and baz") : new(bar, baz, qux)
end

Foo(bar, baz) = Foo(bar, baz, bar+baz)

You can add an outer constructor to do the addition work on construction and use an inner constructor like @Renan_Rabelo suggested to enforce the rule.

It seems easier to only take two arguments in the inner constructor:

struct Foo
    bar
    baz
    qux
    Foo(bar, baz) = new(bar, baz, bar+baz)
end
6 Likes

You make a good point, @stevengj ! I was just thinking a more verbose error might be helpful to someone trying to make a new instance, depending on the situation.

1 Like

If I understand your request correctly, a 2-argument outer constructor does what you’ve asked and there’s no need to fiddle with inner constructors. After all, you said you wanted a default value rather than it to always be exactly a particular value (which is where an inner constructor would have been useful).

struct Foo
    bar
    baz
    qux
end
Foo(bar,baz) = Foo(bar,baz,bar+baz)

Foo(1,2) # == Foo(1, 2, 3)
Foo(1,2,4) # == Foo(1, 2, 4)
5 Likes

Thank you for the nice examples which prompted me to try a variation for a slightly different use case.

If I want to generate a structure but with a different type than the structure demands. I can use an outer constructor to do the conversion and generate the structure as follows:

julia> struct Foo
           bar::Real
           bas::Real
           qux::Real
       end

julia> Foo(bar,baz,qux::String) = Foo(bar,baz,parse(Int, qux))
Foo

julia> foo2 = Foo(1,1,"1")
Foo(1, 1, 1)

julia> foo1 = Foo(1,1,1)
Foo(1, 1, 1)
1 Like