Surprising type result with @

Hi everyone,

I am quite confused about the resulting types in below snippet:

N = 5
T = Float32

# edit, forgot to mention these variables
μ = rand(T, N_states, 1)
σ = rand(T, N_states, 1)

E₀ = fill(T(0.5), N, 1)                           #  5×1 Matrix{Float32}
U₀_1 = @. ((1 - μ) * σ) * E₀                      #  5×1 Matrix{Float32}
U₀_2 = @. (1 - μ) * σ * fill(T(0.5), N, 1)        #  5×1 Matrix{Matrix{Float32}}

Can someone please explain why U₀_2 has a different type than U₀_1, despite typeof(fill(T(0.5), N_states, 1)) being equal to typeof(E₀)?

I can’t reproduce on julia 1.10.2 but I guess this is because @. applies to fill as well. Can you try U₀_2 = fill(T(0.5), N, 1) .* (@. (1 - μ) * σ)?

2 Likes

What is μ and σ? And which version of julia are you running?

1 Like

@sgaure Oops, my bad, I added the variables to the MWE
@artemsolod It seems you are correct, your variant works on Julia 1.9.3, too

Thanks for the answers!

Yes, it’s the difference between

julia> ((1 .- μ) .* σ) .* fill(T(0.5), N, 1)
5×1 Matrix{Float32}:

and

julia> ((1 .- μ) .* σ) .* fill.(T(0.5), N, 1)
5×1 Matrix{Matrix{Float32}}:

where the broadcasts are fused, and the fill broadcast computes fill(T(0.5),N,1) every time. I agree it’s a bit unexpected.

1 Like

It appears broadcast can be escaped with $:

julia> @. fill(1., (1,2))
([1.0], [1.0, 1.0])

julia> @. $fill(1., (1,2))
1×2 Matrix{Float64}:
 1.0  1.0

Great post: Broadcasting in Julia: the Good, the Bad, and the Ugly | Blog by Bogumił Kamiński

1 Like