Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Broadcasting struct creation with `Base.@kwdef`

Tags:

julia

If I have a large struct that I want to create an array of (e.g. to later create a StructArray), how can I create an array of structs when I have keyword defaults.

E.g.

Base.@kwdef struct MyType
  a = 0
  b = 0
  c = 0
  d = 0
  ... # can be up to 10 or 20 fields
end

Base.@kwdef is nice because I can create objects with MyType(b=10,e=5) but sometimes I have arrays of the argument. I would like to be able to broadcast or succinctly construct an array of the structs.

That is I would like the following would create an array of three MyTypes: MyType.(c=[5,6,7],d = [1,2,3])

Instead, it creates a single MyType where c and d are arrays rather than scalar values.

What are ways to keep the convenience of both Base.@kwdef and easy array of struct construction?

like image 473
Alec Avatar asked Oct 22 '25 07:10

Alec


2 Answers

Seems like a good use case for a comprehension:

julia> [MyType(c=cval, d=dval) for (cval, dval) in zip([5, 6, 7], [1, 2, 3])]
3-element Vector{MyType}:
 MyType(0, 0, 5, 1)
 MyType(0, 0, 6, 2)
 MyType(0, 0, 7, 3)

Another possiblity (based on this answer ) is to explicitly do the broadcast call yourself:

julia> broadcast((cval, dval) -> MyType(c = cval, d = dval), [5, 6, 7], [1, 2, 3])
3-element Vector{MyType}:
 MyType(0, 0, 5, 1)
 MyType(0, 0, 6, 2)
 MyType(0, 0, 7, 3)

or the equivalent ((cval, dval) -> MyType(c = cval, d = dval)).([5, 6, 7], [1, 2, 3]) as mentioned in the comment there.

Out of these, the array comprehension seems to me the clearest and most obvious way to go about it.

like image 126
Sundar R Avatar answered Oct 25 '25 14:10

Sundar R


Following this post: https://github.com/JuliaLang/julia/issues/34737 there is no nice built-in syntax for your case. One option is comprehension (see the other answer), second option (which I prefer here more) is building an anonymous function and vectoring over it such as:

julia> ((x,y)->MyType(;c=x,d=y)).([1,2],[3,5])
2-element Vector{MyType}:
 MyType(0, 0, 1, 3)
 MyType(0, 0, 2, 5)

It is also possible to call broadcast directly as:

julia> broadcast((x,y)->MyType(;c=x,d=y), [1,2],[3,5])
2-element Vector{MyType}:
 MyType(0, 0, 1, 3)
 MyType(0, 0, 2, 5)
like image 33
Przemyslaw Szufel Avatar answered Oct 25 '25 13:10

Przemyslaw Szufel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!