Why array slices can't be passed to a function by reference?

Imagine we have an array and we want to change it inside a function:

function set_ones!(x)
    x[:,:] .= 1
end

arr = zeros(5)
set_ones!(arr)
println(arr)

It works just as expected. Result:

[1.0, 1.0, 1.0, 1.0, 1.0]

But if we want change only part of the array:

arr2 = zeros(5)
set_ones!(arr2[1:3])
println(arr2)

Result:

[0.0, 0.0, 0.0, 0.0, 0.0]

Is it how it supposed to work, or is it a bug?

1 Like

Slicing produces copies. Pass a view.

2 Likes

See also: https://docs.julialang.org/en/stable/manual/performance-tips/#Consider-using-views-for-slices-1

1 Like

There is a convenient macro for this which works here

julia> @views set_ones!(arr2[1:3])
3×1 SubArray{Float64,2,Base.ReshapedArray{Float64,2,SubArray{Float64,1,Array{Float64,1},Tuple{UnitRange{Int64}},true},Tuple{}},Tuple{Base.Slice{Base.OneTo{Int64}},Base.Slice{Base.OneTo{Int64}}},true}:
 1.0
 1.0
 1.0

julia> println(arr2)
[1.0, 1.0, 1.0, 0.0, 0.0]
3 Likes

Wow, thank you a lot!