# Setproperty!/getproperty and broadcasting do not seem to work together

**URL:** https://discourse.julialang.org/t/setproperty-getproperty-and-broadcasting-do-not-seem-to-work-together/19907
**Category:** General Usage
**Tags:** question, faq, broadcast
**Created:** [January 22, 2019, 2:08am UTC](https://discourse.julialang.org/t/setproperty-getproperty-and-broadcasting-do-not-seem-to-work-together/19907 "2019-01-22T02:08:08Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)
#### Post date: [January 22, 2019, 2:08am UTC](https://discourse.julialang.org/t/setproperty-getproperty-and-broadcasting-do-not-seem-to-work-together/19907/1 "2019-01-22T02:08:08Z")

</div>

I can not make `object.property .+= value` work where `property` is implemented in `setproperty!`. Here is example code:

```julia
struct MyStruct
    an_array::Array{Int,1}
end

function Base.getproperty(s::MyStruct, name::Symbol)
    if name==:subarray
        s.an_array[2:end]
    else
        getfield(s,name)
    end
end

function Base.setproperty!(s::MyStruct, name::Symbol, x)
    if name==:subarray
        s.an_array[2:end] = x
    else
        setfield!(s,name,x)
    end
end

s = MyStruct([1,2,3])
s.subarray .+= [20,30]

```

This results in `MyStruct([1, 2, 3])` when I would expect the result to be `MyStruct([1, 22, 33])`.

I tried making it a `mutable struct` but that did not work either.

What am I doing wrong here? Is this a Julia bug?

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [January 22, 2019, 2:19am UTC](https://discourse.julialang.org/t/setproperty-getproperty-and-broadcasting-do-not-seem-to-work-together/19907/2 "2019-01-22T02:19:32Z")

</div>

> [@Krastanov](#):
>
> `s.subarray .+= [20,30]`

This is essentially syntactic sugar for `broadcast!(+, s.subarray, s.subarray, [20,30])`, so it never calls your `setproperty!` method.

Probably you just want to change your `getproperty` method to return `@view s.an_array[2:end]` rather than a copy.

---

<div class="post-metadata">

### Author: ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)
#### Post date: [January 22, 2019, 6:43pm UTC](https://discourse.julialang.org/t/setproperty-getproperty-and-broadcasting-do-not-seem-to-work-together/19907/3 "2019-01-22T18:43:46Z")

</div>

Thanks for the explanation!

For completeness, here is the (misunderstood) example code that led me to (wrongly) believe a `@view` is not necessary:

```julia
a = [1,2,3]
a[2:3] .+= [20,30] # no copying, because the indexing is on the left side 
b = a[2:3] # this is a copy, as the indexing is on the right side
b .+= [200,300]

```

Now `a` is `[1,22,33]`, while `b` is `[222,333]`.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [January 22, 2019, 7:11pm UTC](https://discourse.julialang.org/t/setproperty-getproperty-and-broadcasting-do-not-seem-to-work-together/19907/4 "2019-01-22T19:11:28Z")

</div>

It might be helpful to think of the `.=` as the “broadcast into” operation.

- `a .= ...` broadcasts into `a` itself.
- `a[1] .= ...` broadcasts into the object that `a[1]` returns.
- `a.prop .= ...` broadcasts into the object that `a.prop` returns.
- `a[2:3] .= ...` effectively broadcasts into `a[2:3]`. It is indeed a little special because — unlike the other three forms — if we just modified the thing that `a[2:3]` normally returns we wouldn’t change `a` at all!

You can even do funny things that you cannot do with the normal (non-broadcast) `=`, like `f(1) .= ...`, which broadcasts into whatever `f(1)` returns.

So the point is that you’re not really doing `setproperty!` at all when you use `.=`.

---

<div class="post-metadata">

### Author: ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)
#### Post date: [January 22, 2019, 7:29pm UTC](https://discourse.julialang.org/t/setproperty-getproperty-and-broadcasting-do-not-seem-to-work-together/19907/5 "2019-01-22T19:29:23Z")

</div>

Could you elaborate on the “special” case?

> [@mbauman](#):
>
> `a[2:3] .= ...`

Is this still just rewritten into a `broadcast!` call? I do not get how this can be true without creating a copy…

Especially given that `a[1] .= ...` does not have the same “special” behavior.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [January 22, 2019, 7:59pm UTC](https://discourse.julialang.org/t/setproperty-getproperty-and-broadcasting-do-not-seem-to-work-together/19907/6 "2019-01-22T19:59:48Z")

</div>

The point is that — at a high level — `LHS .= RHS` broadcasts into whatever the left hand side returns. We make an exception for non-scalar indexing because it simply wouldn’t be useful to modify the new container that non-scalar indexing would normally return.

Now if you’re curious about its implementation, the syntax `x[i] .= y` is essentially lowered to `broadcast!(identity, @views(x[i]), y)`. The Julia parser identifies that there was an indexing expression on the LHS and inserts an extra transform in those cases. The `@views` macro will return an element if all indices are scalar numbers, and a view otherwise. It’s more complicated than that, though, due to broadcast fusion and such, but the behavior is the same.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [January 22, 2019, 8:17pm UTC](https://discourse.julialang.org/t/setproperty-getproperty-and-broadcasting-do-not-seem-to-work-together/19907/7 "2019-01-22T20:17:50Z")

</div>

> [@Krastanov](#):
>
> Is `a[2:3] .= ...` still just rewritten into a `broadcast!` call? I do not get how this can be true without creating a copy…

No, see the [comment here](https://github.com/JuliaLang/julia/blob/b9579594163b9ed30e2017298fec0665ab0cdbf0/base/broadcast.jl#L1102-L1112).

`a[foo...] .= ...` is rewritten into `broadcast!(identity, Base.dotview(a, foo...), ...)`. The `Base.dotview` function, which in turn calls `Base.maybeview` (which is used for the `@views` macro), defaults to `getindex`, but [returns a view for slicing operations](https://github.com/JuliaLang/julia/blob/b9579594163b9ed30e2017298fec0665ab0cdbf0/base/views.jl#L121-L127) like `a[1:2]` where `a` is an `AbstractArray`.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [January 22, 2019, 8:30pm UTC](https://discourse.julialang.org/t/setproperty-getproperty-and-broadcasting-do-not-seem-to-work-together/19907/8 "2019-01-22T20:30:30Z")

</div>

We don’t actually lower to `broadcast!` directly anymore due to the run-time representation of fusion, but the end result is the same. It’s easier to think about it as though it still did, but this mental model will break if you try to overload `broadcast!`.
