Submatrix replacement error in a matrix

In this below code there is a weird error message:

joja = [1 2 3; 4 5 6; 7 8 9] 
joja[2:3,2:3] =  [1 2; 3 4 ] # ok
joja2 = reshape(1:9,3,3) 
joja2[2:3,2:3] =  [1 2; 3 4 ] # error (reshaped array)
joja3 = copy(joja2)
joja3[2:3,2:3] =  [1 2; 3 4 ] # ok

I know that reshaped array is a different animal, but why it happens?

Please report the exact error by copying and pasting an actual Julia session.

Thanks for your feedback

The two lines that generates an error (in the middle) was

Julia >joja2 = reshape(1:9,3,3)
3×3 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}:
 1  4  7
 2  5  8
 3  6  9

Julia>joja2[2:3,2:3] =  [1 2; 3 4 ]
ERROR: indexed assignment fails for a reshaped range; consider calling collect
Stacktrace:
 [1] macro expansion at .\multidimensional.jl:558 [inlined]
 [2] macro expansion at .\cartesian.jl:64 [inlined]
 [3] macro expansion at .\multidimensional.jl:556 [inlined]
 [4] _unsafe_setindex!(::IndexLinear, ::Base.ReshapedArray{Int64,2,UnitRange{Int
64},Tuple{}}, ::Array{Int64,2}, ::UnitRange{Int64}, ::UnitRange{Int64}) at .\mul
tidimensional.jl:549
 [5] macro expansion at .\multidimensional.jl:541 [inlined]
 [6] _setindex! at .\multidimensional.jl:537 [inlined]
 [7] setindex!(::Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}, ::Array{I
nt64,2}, ::UnitRange{Int64}, ::UnitRange{Int64}) at .\abstractarray.jl:968

A simular approach it’s ok, but uses pure array instead reshaped array

Julia>joja = [1 2 3; 4 5 6; 7 8 9]
3×3 Array{Int64,2}:
 1  2  3
 4  5  6
 7  8  9

Julia>joja[2:3,2:3] =  [1 2; 3 4 ]
2×2 Array{Int64,2}:
 1  2
 3  4

There is no setindex! for ranges. The error suggests you to collect it as a regular array first then assign values.

@tomaklutfu, in that case is not a range, is a real array, because reshape function get a range and convert it to an array in any shape.

However, it’s a little bit different from a declared array in the second piece of code. It’s a reshaped array (ReshapedArray in the error message) so it generates an error, but it lacks logic!

Notice that there is no 3D ranges, but reshape function produces 3D arrays:

vet = reshape(1:24,2,3,4)
println(vet[1,2,3])   # shows 15.

A reshaped range is not the same as a reshaped Array. Ranges (even reshaped ones) are read-only. This is intentional language behavior. As the previous response suggests, you can first convert the range to a Vector via a call to theVector constructor or to collect.

@Stephen_Vavasis, you are right! This reshaped range is read-only. I’ve got it. copy() or collect() do the job. Thanks for your explanation.

It’s pretty amazing so much power in a programming language.

The below code works!

Vals = [30 60; 45 30]
Dest = collect(reshape(1.:9.,3,3))
Dest[2:3,2:3] = sind.(Vals) .* cosd.(Vals)

Before submatrix assignment:

Julia> Dest
3×3 Array{Float64,2}:
1.0 4.0 7.0
2.0 5.0 8.0
3.0 6.0 9.0

After:

Julia> Dest
3×3 Array{Float64,2}:
1.0 4.0 7.0
2.0 0.433013 0.433013
3.0 0.5 0.433013