Why is it possible to change the values of a row of a given matrix with a new matrix?

I tried to pick an exact and explicit title for this question but failed. So I guess you must read my entire question to understand the issue.
In Julia, we can define a random 2*5 Matrix using rand(2,5):

julia> a = rand(2,5)
2×5 Matrix{Float64}:
 0.471737  0.726199  0.575673  0.760658  0.300233
 0.443542  0.92782   0.501209  0.902491  0.171455

And what amazed me (Also warned me a lot) is that you can change the values of a[1, 1:4] by assigning (=) a 2*2 Matrix:

julia> a[1 , 1:4] = [1 2;3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> a
2×5 Matrix{Float64}:
 1.0       3.0      2.0       4.0       0.300233
 0.443542  0.92782  0.501209  0.902491  0.171455

I mean, This is not good at all and can cause many silent problems in many algorithms! How and most importantly, why even is this possible to assign a matrix into a piece of a vector! I mean, a[1, 1:4] is a vector:

julia> a[1, 1:4]
4-element Vector{Float64}:

Which belongs to the a matrix, and here I changed that vector with the values of a matrix!! I expected that Julia would throw an error saying: “that dimensions don’t match, so how the hell are you expecting me (Julia) to do that?”.
But not also Julia didn’t throw anything, but it also amazed me in that way! Why is that possible?

1 Like

You may be interested in using .= instead.

julia> a = rand(2,5)
2×5 Matrix{Float64}:
 0.652209  0.773756  0.0126887  0.320912  0.758584
 0.483548  0.278898  0.902765   0.428947  0.0341019

julia> a[1, 1:4] .= [1 2; 3 4]
ERROR: DimensionMismatch("array could not be broadcast to match destination")

Otherwise, setindex_shape_check is designed to do the following:

1 Like

I find implicit raveling is often surprising and error prone. I would rather create a linear view explicitly when I want it, but I don’t think that’s possible in 1.X. A nonraveling view like noravel(b) that errors when raveled could help avoid these issues.

1 Like