# Broadcasting and arrays of arrays

#1

I was hoping that this would work for centering some data that is e.g. `Array{SVector}`

``````d = [rand(2) for i=1:10]
d - mean(d)
``````

``````d .- mean(d)
``````

But they don’t work. I understand why they don’t work, but I’m wondering if it would be possible to have consistent broadcasting rules that would make it work.

For now, I know I can do

``````d .- [mean(d)]
``````

It is just that with scalar elements, one can write

``````d = rand(10)
d - mean(d)
``````

#2

I think the way you typically “scalarize” an object is by enclosing it in a `Ref` so `d .- Ref(mean(d))`

#3

Thanks, that is interesting. It doesn’t appear to do the right thing, however:

``````julia> vs = [[i, i+1] for i=1:10];

julia> mean(vs .- Ref(mean(vs)))
2-element Array{Float64,1}:
0.0
1.0

julia> mean(vs .- [mean(vs)])
2-element Array{Float64,1}:
0.0
0.0

julia> [zeros(2)] .+ Ref(mean(vs))
1-element Array{Array{Float64,1},1}:
[5.5, 5.5]

julia> [zeros(2)] .+ [mean(vs)]
1-element Array{Array{Float64,1},1}:
[5.5, 6.5]
``````

#4

I’m honestly not sure how Ref is supposed to work but I think the reason it doesn’t work here boils down to

``````julia> x = Ref([1, 2])
Base.RefArray{Int64,Array{Int64,1},Void}([1, 2], 1, nothing)

julia> x[]
1
``````

It does work to instead use Base.RefValue but it’s unexported and undocumented, probably for a reason. Some other options, with or without broadcasting:

``````[x - mean(d) for x in d]
map(x -> x - mean(d), d)
(x -> x - mean(d)).(d)
``````

#5

Your other options all work, but are going to re-compute `mean(d)` for every element.

I’m also super surprised by the behavior of Ref in this case, but I guess `RefArray`s behave differently in broadcast? In particular, it looks like a RefArray behaves like a scalar but only using the first element of the contained array. A 1-element tuple has the behavior I would expect, as does wrapping the array in a 1-element array.

``````julia> [1, 2] .- ([1, 2],)
2-element Array{Array{Int64,1},1}:
[0, -1]
[1, 0]

julia> [1, 2] .- Ref([1, 2])  # behaves like [1, 2] .- [1]
2-element Array{Int64,1}:
0
1

julia> [1, 2] .- [[1, 2]]
2-element Array{Array{Int64,1},1}:
[0, -1]
[1, 0]
``````

this is surprising enough that I might consider it a broadcast bug.

#7

Thanks for the replies. I agree that it’s surprising and can’t think of any reason why it should be like that. We’ll see: https://github.com/JuliaLang/julia/issues/24880

I still hope there is a way to make any expression
`A - a` or `A .- a` work if `eltype(A) == typeof(a)`, even if `typeof(a)` is an array.

#8

Also `d .- (mean(d),)` works.

#9

I just noticed `StaticArrays` has `Scalar`, which seems to do the right thing even for non-StaticArray types:

so yet another option, in the spirit of `Ref` is: `d .- Scalar(mean(d))`

#10

Interesting. Having `Scalar` in `Base` would make sense.