# Broadcasted assignment of custom types

**URL:** <https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198>\
**Category:** General Usage\
**Tags:** broadcast\
**Created:** [January 2, 2019, 4:00pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198 "2019-01-02T16:00:46Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![BioTurboNick](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bioturbonick/32/6380_2.png) [@BioTurboNick](https://discourse.julialang.org/u/BioTurboNick)\
**Post date:** [January 2, 2019, 4:00pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/1 "2019-01-02T16:00:46Z")

</div>

This works natively:

```julia
a = Vector{Int}(undef, 2)
a .= 2

```

However, this does not work, failing with a cryptic error:

```julia
struct Foo
    x::Int
end
a = Vector{Foo}(undef, 2)
a .= Foo(2)
#=
ERROR: MethodError: no method matching length(::Foo)
Stacktrace:
 [1] _similar_for(::UnitRange{Int64}, ::Type, ::Foo, ::Base.HasLength) at .\array.jl:532
 [2] _collect(::UnitRange{Int64}, ::Foo, ::Base.HasEltype,
::Base.HasLength) at .\array.jl:563
 [3] collect(::Foo) at .\array.jl:557
 [4] broadcastable(::Foo) at .\broadcast.jl:617
 [5] broadcasted(::Function, ::Foo) at .\broadcast.jl:1166
 [6] top-level scope at none:0
=#

```

Is there a reason not to provide for broadcasted assignment of custom types into an array of that type?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [January 2, 2019, 4:04pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/2 "2019-01-02T16:04:32Z")

</div>

> [@BioTurboNick](#):
>
> Is there a reason not to provide for broadcasted assignment of custom types into an array of that type?

Types default to be iterable-y and not scalar-y. So do something like:

```julia
julia> a .= (Foo(2),)
2-element Array{Foo,1}:
 Foo(2)
 Foo(2)

```

or define

```julia
julia> Broadcast.broadcastable(a::Foo) = (a,)

julia> a .= Foo(2)
2-element Array{Foo,1}:
 Foo(2)
 Foo(2)

```

---

<div class="post-metadata">

**Author:** ![BioTurboNick](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bioturbonick/32/6380_2.png) [@BioTurboNick](https://discourse.julialang.org/u/BioTurboNick)\
**Post date:** [January 2, 2019, 4:06pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/3 "2019-01-02T16:06:30Z")

</div>

Interesting, okay. Would it do any harm, or is it possible, to detect if `length` is defined for a type, and if not, treat it as scalar? (Thinking about whether it is worth suggesting a change to the language)

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [January 2, 2019, 4:19pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/4 "2019-01-02T16:19:22Z")

</div>

See [recent broadcast changes (iterate by default), scalar struct, and `@.`](https://discourse.julialang.org/t/recent-broadcast-changes-iterate-by-default-scalar-struct-and/11178) and linked issues/PRs.

---

<div class="post-metadata">

**Author:** ![BioTurboNick](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bioturbonick/32/6380_2.png) [@BioTurboNick](https://discourse.julialang.org/u/BioTurboNick)\
**Post date:** [January 2, 2019, 4:21pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/5 "2019-01-02T16:21:57Z")

</div>

@kristoffer.carlsson, Your suggestion allows me to broadcast to an array range, but not to a single element of the array.

```julia
a = Vector{Foo}(undef, 3)
a[1:2] .= Foo(2) # works
a[3] .= Foo(2) # error
#=
ERROR: MethodError: no method matching size(::Foo)
Stacktrace:
 [1] axes at .\abstractarray.jl:75 [inlined]
 [2] materialize!(::Foo, ::Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple},Nothing,typeof(identity),Tuple{Tuple{Foo}}}) at .\broadcast.jl:759
 [3] top-level scope at none:0
=# 

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [January 2, 2019, 4:29pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/6 "2019-01-02T16:29:46Z")

</div>

Use `=` for that? It doesn’t work for other types either.

---

<div class="post-metadata">

**Author:** ![BioTurboNick](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bioturbonick/32/6380_2.png) [@BioTurboNick](https://discourse.julialang.org/u/BioTurboNick)\
**Post date:** [January 2, 2019, 4:33pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/8 "2019-01-02T16:33:21Z")

</div>

Ah, nevermind the deleted post, I thought it worked for numbers.

Okay, so I need to check whether my array lookup will be one element or multiple elements and then have special cases for each? Seems like that shouldn’t be necessary.

EDIT: Ah, so a[3:3] works okay but a[3] does not. That’s okay then, I suppose.

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [January 2, 2019, 6:31pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/9 "2019-01-02T18:31:48Z")

</div>

I might be stating the obvious, but beware it’s one and the same object, which can lead to surprises if your objects are not fully immutable:

```julia
julia> struct Foo x::Vector{Int} end

julia> a = Vector{Foo}(undef, 2);

julia> a .= (Foo([2]),)
2-element Array{Foo,1}:
 Foo([2])
 Foo([2])

julia> push!(a[1].x, 3);

julia> a
2-element Array{Foo,1}:
 Foo([2, 3])
 Foo([2, 3])

```

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [January 2, 2019, 7:22pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/10 "2019-01-02T19:22:23Z")

</div>

Btw, another way of creating `a` with identical objects is:

```julia
julia> struct Foo x::Vector{Int} end

julia> a = fill(Foo([2]), 2)
2-element Array{Foo,1}:
 Foo([2])
 Foo([2])

```

(There’s also `fill!`.) In case you want unique objects, you can do:

```julia
julia> a = 1:2 .|>_-> Foo([2])
2-element Array{Foo,1}:
 Foo([2])
 Foo([2])

julia> push!(a[1].x, 3);

julia> a
2-element Array{Foo,1}:
 Foo([2, 3])
 Foo([2])

```

---

<div class="post-metadata">

**Author:** ![BioTurboNick](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bioturbonick/32/6380_2.png) [@BioTurboNick](https://discourse.julialang.org/u/BioTurboNick)\
**Post date:** [January 2, 2019, 7:52pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/11 "2019-01-02T19:52:35Z")

</div>

@bennedich - Took me a moment to realize what you were saying, that only one object is created and then each array item points to it. Thank you, that’s good to remember.

---

<div class="post-metadata">

**Author:** ![BioTurboNick](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bioturbonick/32/6380_2.png) [@BioTurboNick](https://discourse.julialang.org/u/BioTurboNick)\
**Post date:** [January 2, 2019, 7:54pm UTC](https://discourse.julialang.org/t/broadcasted-assignment-of-custom-types/19198/12 "2019-01-02T19:54:32Z")

</div>

Also, didn’t know Julia had the |\> operator for function chaining, so thanks for showing me that.
