I have a struct with lots of different members, all of which get initialized in a standard way. Currently, my code looks like
struct A
a::Int
b::Int
c::Int
function A()
a = 1
b = 1
c = 1
new(a, b, c)
end
end
which looks fine for three variables, but if I had, say, 40 of them, then the final call to new() starts to look very ugly and I have to be very careful about where I enter in the variables. Is there any better way to do this, for example automatically initializing the struct based on the fact that the variable names in the constructor are the same as in the struct definition?
The Base.@kwdef macro might help here. It lets you give default values to members, and initialize them with keywords.
That being said, if you have 40 members in a struct, I wonder if you might want to use some other data structure instead, something you can loop/iterate over.
For such scenarios (where you have the defaults for your field values) is better to use the @kwdef approach (note that you no longer need to use new() for setting your defaults):
@kwdef struct A
a::Int=1
b::Int=1
c::Int=1
d::Int=2
end
This will generate a few constructors for you. Besides the default constructor you are also getting a keyword-based constructor.
Ways you can instantiate your A after defining your struct with @kwdef:
Thanks! I’ll take a look at this macro. Unfortunately, for my particular context, I think the code is ultimately more readable if all the different entries are kept separate, as all their uses are quite different. I’ll think more about it though, as I share your discomfort with such an unwieldy structure.
julia> using Parameters
julia> @with_kw struct A
a::Int = 6
b::Float64 = -1.1
c::UInt8
end
julia> A(c=4)
A
a: 6
b: -1.1
c: 4
julia> A()
ERROR: Field 'c' has no default, supply it with keyword.
julia> A(c=4, a = 2)
A
a: 2
b: -1.1
c: 4
With that many fields, I suspect that you should group them into multiple sub-types. A single struct with 40 plain primitive fields seems a bit alien to me.