Struct variables explicit setting

Hi!
I know how to do this:

struct a
       a1
       a2
       a3
end
b=a(1,2,3)

I was wondering if there’s a way to do this in a more explicit way. Something like: b=a(a1=1,a2=2,a3=3).
The reason would be readability (so one would know what the variables of the struct are without having to know the right order to put them in. So ideally, b=a(a3=3,a1=1,a2=2) would also work.
Is this supported or would it take a lot of code to achieve (like making some fancy functions)?

Also, any disadvantage of using mutable structs vs regular ones?
Thanks a lot!

GitHub - mauro3/Parameters.jl: Types with default field values, keyword constructors and (un-)pack macros may be helpful, or just Base.@kwdef:

Base.@kwdef struct a
    a1
    a2
    a3
end
3 Likes

Cool, @kwdef does exactly what I had in mind. Thanks!

Are there any disadvantages of storing large arrays inside mutable structs?

I’d generally go with a struct over a mutable struct where possible, but it really depends on the application. Good idea to provide your type definitions with concrete field types as a first step: Performance Tips · The Julia Language. Most of that page is worth a good read if you want to get decent performance :slight_smile:

If you want a more customized solution than offered by Base.@kwdef, you need to write your own constructor methods: Constructors · The Julia Language

You better start another thread for this, different, question.

1 Like

I’m planning on using structs to avoid passing too many variables to functions and having messy code. All my variables will have very defined types. Would this be a good way to do it, performance-wise?

mutable struct thing
a::Float64
b::Array{StaticArrays.SVector{3,Float64}}
c::Array{StaticArrays.SVector{Int}}  # this one can have 3 or 4 elements in the SArray. Not sure how to declare that
d::Array{Float64}
end

Thanks!

Fair enough!

1 Like

I think you’ll probably want to use Vector{T} instead of Array{T}, or explicitly specify the second type parameter (number of dimensions). E.g., Array{T, 3}.

1 Like

Array also seems to work. What’s the difference between using Array and Vector here?

Oh, Array works for Vector and Matrix. So I should use those to be more precise, I guess.

How do I specify the array of 3 or 4 StaticArrays?
Thanks!

Array works for Vector and Matrix

Take a look at: Multi-dimensional Arrays · The Julia Language Quote from there: “An array is a collection of objects stored in a multi-dimensional grid.”

The second type parameter to Array determines the number of dimensions. So Array is more general than you think: it’s not just Vectors and matrices.

I’m not quite sure what you’re asking here?

Array{T}, as opposed to Array{T, N}, for some constant T and N, is this kind of type: Types · The Julia Language I’m not yet sure how do those work, but I suspect that using them as fields in a struct may lead to unintended effects.

I mean how do I declare that a variable in my struct will be like this one:

a=[SA[1,2,3],SA[1,2,3,4],SA[1,2,3];

I’d think something like a::Vector{StaticArrays.SVector{Int}}, but that does not work.
Thanks!

This is ugly, but works:
Array{SArray{S,Int64,1,L} where L where S<:Tuple,1}
Thanks for the help, folks!

That’s a UnionAll type (I mentioned those above). I think using a (small) Union type is better than a UnionAll:

julia> T = Int
Int64

julia> Union{SVector{3, T}, SVector{4, T}}[SVector{3, T}([1,2,3]), SVector{4, T}([1,2,3,4]), SVector{3, T}([1,2,3])]
3-element Array{Union{SArray{Tuple{3},Int64,1,3}, SArray{Tuple{4},Int64,1,4}},1}:
 [1, 2, 3]
 [1, 2, 3, 4]
 [1, 2, 3]

On the other hand, maybe you just need Tuples? What are your requirements? If you want a better answer, you should probably say what is the problem you’re solving, and give more examples of the values that will be of the type you are seeking for.

Ah, so a::Vector{Union{ SVector{3,Int},SVector{4,Int} }}.
I’m working on a problem that solves equations on large meshes. The vector above contains indices of the nodes of each element in my mesh (which can be a tri or a quad, hence the 3 or 4 condition). I usually use this vector to list all nodes in an element (points[elements[n]], where points is a Vector of StaticArrays containing the x/y/z coordinates of each point, and elements is the Vector of StaticArrays I mentioned above.
Does the information change how I should go around doing this? I’ve been using Julia for a month now, so I’m sure I’m doing many things wrong =P.
Thanks!

I’m also new to Julia, but here’s an idea if you need speed:
Instead of a single Vector, use two Vectors: a Vector{SVector{3,Int}} and a Vector{SVector{4,Int}}. This would mean more code for you to write; but assuming there’s a lot of data in the Vector(s), I think iterating over two Vectors of simpler types would be faster than iterating over a single vector of a more complex type.

1 Like

Huh. That could work. I’ll look into it.
Thanks!

1 Like

GitHub - tkoolen/TypeSortedCollections.jl: Type-stable operations on type-heterogeneous collections generalizes this idea to arbitrary collections of objects, as long as there are relatively few different types of things you want to store.

4 Likes

This is getting a bit advanced for me, but I’ll definitely have a look. Thanks!