# .. broadcast object property

**URL:** https://discourse.julialang.org/t/broadcast-object-property/47104
**Category:** Internals & Design
**Tags:** question, broadcasting, structarrays
**Created:** [September 23, 2020, 2:05am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104 "2020-09-23T02:05:17Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![sashmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sashmit/32/18791_2.png) [@sashmit](https://discourse.julialang.org/u/sashmit)
#### Post date: [October 20, 2020, 5:14am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/22 "2020-10-20T05:14:49Z")

</div>

(post deleted by author)

---

<div class="post-metadata">

### Author: ![zot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zot/32/5817_2.png) [@zot](https://discourse.julialang.org/u/zot)
#### Post date: [November 16, 2021, 3:25am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/23 "2021-11-16T03:25:08Z")

</div>

You could also define

`(s::Symbol)(data) = getproperty(data, s)`

which would let you say

`:x.(Array_of_A)`

---

<div class="post-metadata">

### Author: ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)
#### Post date: [November 16, 2021, 9:39am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/24 "2021-11-16T09:39:51Z")

</div>

would you mind applying to the above example with X T and T1 ?

---

<div class="post-metadata">

### Author: ![zot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zot/32/5817_2.png) [@zot](https://discourse.julialang.org/u/zot)
#### Post date: [November 17, 2021, 6:45am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/25 "2021-11-17T06:45:23Z")

</div>

> [@Lincoln\_Hannah](#):
>
> would you mind applying to the above example with X T and T1 ?

Sure:

```julia
julia> :T1.(:T.([X...])) .+ 0
3-element Vector{Int64}:
 1
 2
 2

```

---

<div class="post-metadata">

### Author: ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)
#### Post date: [November 17, 2021, 6:52am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/26 "2021-11-17T06:52:24Z")

</div>

Thanks 🙂

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [November 18, 2021, 6:09am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/27 "2021-11-18T06:09:46Z")

</div>

This is type-piracy though, and might have unexpected consequences

---

<div class="post-metadata">

### Author: ![zot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zot/32/5817_2.png) [@zot](https://discourse.julialang.org/u/zot)
#### Post date: [November 18, 2021, 7:22am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/28 "2021-11-18T07:22:56Z")

</div>

Is there a way to improve the definition?

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [November 18, 2021, 8:20am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/29 "2021-11-18T08:20:10Z")

</div>

I don’t know of an easy and equally concise way. One way to avoid the piracy is to wrap the `Symbol` in your own type, eg.

```julia
julia> struct MySym
       s :: Symbol
       end

julia> (s::MySym)(data) = getproperty(data, s.s)

julia> MySym(:T1).(MySym(:T).([X...])) .+ 0
3-element Vector{Int64}:
 1
 2
 2

```

---

<div class="post-metadata">

### Author: ![Jollywatt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jollywatt/32/202198_2.png) [@Jollywatt](https://discourse.julialang.org/u/Jollywatt)
#### Post date: [August 5, 2022, 12:06am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/30 "2022-08-05T00:06:34Z")

</div>

One severe pitfall that hasn’t been mentioned is that `..` has a pretty low operator precedence, equal to `:`. So unfortunately we’re stuck with

```julia
julia> :( A..x .^ 2 ) == :( A..(x .^ 2) )
true

```

Which is probably a good thing, because this confirms that `..` was intended by the language designers to be used as a `:`-like range operator, so it’s unlikely that different packages will use it with wildly different semantics…

---

<div class="post-metadata">

### Author: ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)
#### Post date: [February 7, 2024, 4:36am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/31 "2024-02-07T04:36:30Z")

</div>

Any update here?  
I’m working a lot with structures of the form

```julia
X=[
    (;a=(x=1,y=1),b=()),
    (;a=(x=2,y=3),b=()),
]

```

and often want to get an array of `x`. I can do

```julia
⋄(data,s)=getproperty.(data,[s])

X ⋄ :a ⋄ :x

```

which is ok. but something like `X..a..x` would be much better.

---

<div class="post-metadata">

### Author: ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)
#### Post date: [February 7, 2024, 6:07am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/32 "2024-02-07T06:07:05Z")

</div>

[https://juliaobjects.github.io/Accessors.jl/stable/lenses/](https://juliaobjects.github.io/Accessors.jl/stable/lenses/)

```julia
julia> X=[
           (;a=(x=1,y=1),b=()),
           (;a=(x=2,y=3),b=()),
       ];

julia> using Accessors

julia> (@optic _.a.x).(X)
2-element Vector{Int64}:
 1
 2

```

---

<div class="post-metadata">

### Author: ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)
#### Post date: [February 7, 2024, 6:17am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/33 "2024-02-07T06:17:54Z")

</div>

That’s really cool. Thank you.

would it be difficult to extend it to something closer to `X.a.x` say:

```julia
@optic X _.a.x

```

---

<div class="post-metadata">

### Author: ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)
#### Post date: [February 7, 2024, 6:31am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/34 "2024-02-07T06:31:05Z")

</div>

```julia
using Accessors
julia> macro mapoptic(e, v)
           :(map((@optic $e), $v))
       end
@mapoptic (macro with 1 method)

julia> @mapoptic _.a.x X
2-element Vector{Int64}:
 1
 2

```

tho if the interface you really want is just `X.a.x` there should be a way to do that using StructArrays or something.

---

<div class="post-metadata">

### Author: ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)
#### Post date: [February 7, 2024, 8:50am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/35 "2024-02-07T08:50:03Z")

</div>

Indeed StructArrays.jl works well here:

```julia
julia> using StructArrays

julia> X = [
           (;a=(x=1,y=1),b=()),
           (;a=(x=2,y=3),b=()),
       ]
2-element Vector{@NamedTuple{a::@NamedTuple{x::Int64, y::Int64}, b::Tuple{}}}:
 (a = (x = 1, y = 1), b = ())
 (a = (x = 2, y = 3), b = ())

julia> Y = StructArray(X, unwrap=t -> t <: NamedTuple)
2-element StructArray(StructArray(::Vector{Int64}, ::Vector{Int64}), ::Vector{Tuple{}}) with eltype @NamedTuple{a::@NamedTuple{x::Int64, y::Int64}, b::Tuple{}}:
 (a = (x = 1, y = 1), b = ())
 (a = (x = 2, y = 3), b = ())

julia> Y[1]
(a = (x = 1, y = 1), b = ())

julia> Y.a.x
2-element Vector{Int64}:
 1
 2

```

```julia

```

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [February 7, 2024, 12:38pm UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/36 "2024-02-07T12:38:43Z")

</div>

StructArrays are definitely the efficient and convenient data structure for this kind of columnar manipulations! You can store the dataset as a StructArray from the beginning and don’t do any conversions.

Btw, Accessors now export `@o` as an alias for `@optic`, to further encourage using this macro (:  
`map((@o _.a.x), X)` works for all arrays, and for StructArrays it can be made as efficient as `X.a.x`. This optimization is more experimental, and for now is only in `AccessorsExtra.jl`, not in `Accessors.jl` proper.

---

<div class="post-metadata">

### Author: ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)
#### Post date: [February 7, 2024, 10:50pm UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/37 "2024-02-07T22:50:38Z")

</div>

This is brilliant.  
Thank you

---

<div class="post-metadata">

### Author: ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)
#### Post date: [February 14, 2024, 12:42am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/38 "2024-02-14T00:42:18Z")

</div>

Is it possible to get StructArray type syntax but maintain coupling with the underlying vector of Structs ?

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [February 14, 2024, 1:40am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/39 "2024-02-14T01:40:21Z")

</div>

Of course, it’s possible – thanks to Julia composability (:  
One approach is to make separate views of each component of your original array, and put them into a StructArray:

```julia
julia> using StructArrays, FlexiMaps, Accessors

julia> X = [(a=1, b=2), (a=3, b=4)]
2-element Vector{@NamedTuple{a::Int64, b::Int64}}:
 (a = 1, b = 2)
 (a = 3, b = 4)

julia> Y = StructArray(
           a=mapview((@o _.a), X),
           b=mapview((@o _.b), X),
           # repeat for all components you need
       )
2-element StructArray(::FlexiMaps.MappedArray{Int64, 1, PropertyLens{:a}, Vector{@NamedTuple{a::Int64, b::Int64}}}, ::FlexiMaps.MappedArray{Int64, 1, PropertyLens{:b}, Vector{@NamedTuple{a::Int64, b::Int64}}}) with eltype @NamedTuple{a::Int64, b::Int64}:
 (a = 1, b = 2)
 (a = 3, b = 4)

julia> Y[2]
(a = 3, b = 4)

# the new Y array actually refers to X values, and updates correspondingly
julia> Y.a .= [5, 6]
2-element FlexiMaps.MappedArray{Int64, 1, PropertyLens{:a}, Vector{@NamedTuple{a::Int64, b::Int64}}}:
 5
 6

julia> X
2-element Vector{@NamedTuple{a::Int64, b::Int64}}:
 (a = 5, b = 2)
 (a = 6, b = 4)

julia> Y.b[2] = 10
10

julia> X
2-element Vector{@NamedTuple{a::Int64, b::Int64}}:
 (a = 5, b = 2)
 (a = 6, b = 10)

```

But I personally think it’s better to just store your data in a StructArray in the first place. Are there any specific reasons you prefer a basic `Vector` here?

---

<div class="post-metadata">

### Author: ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)
#### Post date: [February 14, 2024, 2:04am UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/40 "2024-02-14T02:04:27Z")

</div>

I use functions to operate on the underlying structures.  
The basic vector is coupled to the underling structs. The StructArray isn’t.

```julia
@kwdef mutable struct X
    a::Int64
    b::Int64
end

SA = StructArray( [X(1,1), X(2,2)] )

function f!( x::X )
    x.a += 10    
end

f!.(SA)
SA.a[1] #1

v = collect(SA)
f!.(v)
v[1].a #11

```

Unless you define it as you’ve done above.  
My underlying structs might have a dozen fields.  
Is there any shorthand to do the below for all fields?

```julia
Y = StructArray(
           a=mapview((@o _.a), X),
           b=mapview((@o _.b), X),
           # repeat for all components you need
       )

```

---

<div class="post-metadata">

### Author: ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)
#### Post date: [February 14, 2024, 1:28pm UTC](https://discourse.julialang.org/t/broadcast-object-property/47104/41 "2024-02-14T13:28:36Z")

</div>

This is a common issue with StructArrays, see this page from the documentation: [Some counterintuitive behaviors · StructArrays](https://juliaarrays.github.io/StructArrays.jl/stable/counterintuitive/)

When you do `SA[1]` it creates an `X` struct on the fly. The `f!.(SA)` call operates on these on-the-fly structs so it has no effect: the on-the-fly structs are discarded at the end of the `f!` call.

To work around this, you can work on “lazy rows” rather than temporary structs:

```julia
using StructArrays

@kwdef mutable struct X
    a::Int64
    b::Int64
end

SA = StructArray( [X(1,1), X(2,2)] )

function f!( x )
    x.a += 10    
end

f!.(LazyRows(SA))
SA.a[1] #11

```

[Previous page](https://discourse.julialang.org/t/broadcast-object-property/47104.md?page=1)

[Next page](https://discourse.julialang.org/t/broadcast-object-property/47104.md?page=3)
