# Assigning to a view of an array

**URL:** <https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869>\
**Category:** New to Julia\
**Tags:** arrays, views\
**Created:** [October 3, 2025, 10:27pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869 "2025-10-03T22:27:01Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![DanimirD](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@DanimirD](https://discourse.julialang.org/u/DanimirD)\
**Post date:** [October 3, 2025, 10:27pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/1 "2025-10-03T22:27:01Z")

</div>

The purpose of creating a _view_ from an array is to avoid a copy.

However, a view cannot be assigned to.

```julia-auto
julia> X = rand(3,3)
3×3 Matrix{Float64}:
0.135318 0.958828 0.0860895
0.715183 0.136236 0.542946
0.513489 0.974295 0.155925

julia> @views sX = X[1:2,1:2]
2×2 view(::Matrix{Float64}, 1:2, 1:2) with eltype Float64:
0.135318 0.958828
0.715183 0.136236

julia> sX = rand(2,2)
2×2 Matrix{Float64}:
0.57039 0.679983
0.914289 0.189875

julia> X
3×3 Matrix{Float64}:
0.135318 0.958828 0.0860895
0.715183 0.136236 0.542946
0.513489 0.974295 0.155925

```

As we can see, the attempt to assign to ‘sX’ creates a copy after all. Doesn’t this behavior annul the purpose of creating a view?

‘sX += I(2)’ would create a new array in similar fashion.

Only an additional slicing of ‘sX’ can change the values of the original array.

```julia-auto
julia> sX[:] = rand(2,2)
2×2 Matrix{Float64}:
0.349409 0.523326
0.0127737 0.0894792

julia> X
3×3 Matrix{Float64}:
0.349409 0.523326 0.0860895
0.0127737 0.0894792 0.542946
0.513489 0.974295 0.155925

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [October 3, 2025, 10:33pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/2 "2025-10-03T22:33:35Z")

</div>

> [@DanimirD](#):
>
> the attempt to assign to ‘sX’

is an assignment to the _variable_ `sX`, not the elements of the view previously assigned to it. Slicing specifies elements, so would `sX .= rand(2,2)`.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [October 3, 2025, 10:53pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/3 "2025-10-03T22:53:48Z")

</div>

`=` doesn’t mean what you think it means. See [“assignment vs. mutation” in the Julia manual](https://docs.julialang.org/en/v1/manual/variables/#man-assignment-expressions).

To replace the contents of an array with another array, you can do `a[:] = …` (`setindex!`) or `a .= …` (in-place broadcasting), or a loop where you set elements individually, or some in-place function call like `rand!(a)`.

---

<div class="post-metadata">

**Author:** ![DanimirD](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@DanimirD](https://discourse.julialang.org/u/DanimirD)\
**Post date:** [October 4, 2025, 9:12am UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/4 "2025-10-04T09:12:48Z")

</div>

`sX`is a _view_ of an array.  
I don’t understand what is going on under the hood here.

`sX += I`should not produce a copy, because it has implicitly changed the type of `sX`from SubArray to Array.  
I see only one explanations that would explain this behavior,

namely that there is promotion defined for `SubArray`and `Array`, which is being called here

but I would argue that it should not behave like this:

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [October 4, 2025, 9:42am UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/5 "2025-10-04T09:42:48Z")

</div>

> [@DanimirD](#):
>
> `sX`is a _view_ of an array.  
> I don’t understand what is going on under the hood here.

The confusion has nothing to do with views or even with arrays. It’s just that, as indicated above, you misunderstood the semantics of the `=` syntax:

- `a = b`: assign the value `b` to variable `a`

- `a[i] = b`: `setindex!(a, b, i)`

- `a += b`: `a = a + b`

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [October 4, 2025, 9:53am UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/6 "2025-10-04T09:53:32Z")

</div>

Forget what sX was.  
Whatever the name sX was referring to, with sX = something\_else you are telling Julia that the name sX must now point to the new something\_else object, it doesn’t change in any way the original object sX was referring to.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [October 4, 2025, 10:16am UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/7 "2025-10-04T10:16:52Z")

</div>

> [@nsajko](#):
>
> `a = b`: assign the value `b` to variable `a`

> [@DanimirD](#):
>
> `sX`is a _view_ of an array.

I’m starting to suspect DanimirD is expecting behavior found in another language, which isn’t a good assumption to make unless specified otherwise e.g. Octave from MATLAB. In any case, it’ll help to speak more precisely than this to avoid confusion from other backgrounds.

The very first sentence of the Manual page Variables states plainly:

> A variable, in Julia, is a name associated (or bound) to a value.

A variable isn’t a named value as you might find in other languages, it’s really just a name. This is a common paradigm in dynamically typed languages; if you allow variables to have any type at runtime, then it doesn’t make sense to make a value or its type part of the variable’s identity on the language level (though compiler implementations can leverage some patterns). So `a = b` really means:

1. access the value assigned to variable `b`
2. assign said value to variable `a`

Likewise, `sX = rand(2,2)` means:

1. access the function assigned to `rand`
2. call said function for inputs `(2,2)` to get a 2x2 `Matrix{Float64}`
3. assign said matrix to variable `sX`

Note that the view previously assigned to `sX` was not involved at all, in fact it just lost its only binding so it doesn’t exist anymore on the language level (runtime implementation would have to free that memory automatically).

We may say “value `b`”, “function `rand`”, or “view `sX`” as shorthand, especially when the variable is `const` in a global scope, but it always means “the value currently assigned to this variable.”

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [October 4, 2025, 10:37am UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/8 "2025-10-04T10:37:55Z")

</div>

> [@DanimirD](#):
>
> `sX += I`should not produce a copy

I guess Danimir was wondering the last command in the following block

```julia
julia> X = rand(3,3);

julia> sX = view(X, 1:2, 1:2)
2×2 view(::Matrix{Float64}, 1:2, 1:2) with eltype Float64:
 0.0748389 0.712181
 0.247739 0.453418

julia> sX = sX + [1 0; 0 1]
2×2 Matrix{Float64}:
 1.07484 0.712181
 0.247739 1.45342

```

(Because I also do not fully understand)  
What are the precise processes happened when julia perform  
`sX + [1 0; 0 1]`?  
the former is a view, the latter is a Matrix.  
Is there any middleman object? or allocations? (I don’t fully understand the meaning of “allocation” in computer systems)

Perhaps this makes some sense

```julia
julia> const a = [1];

julia> const b = [1];

julia> @allocated a + b
64

julia> @allocated broadcast!(+, a, a, b)
0

julia> println("a = $a, b = $b")
a = [2], b = [1]

julia> @allocated broadcast!(+, a, a, b)
0

julia> println("a = $a, b = $b")
a = [3], b = [1]

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 4, 2025, 11:50am UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/9 "2025-10-04T11:50:22Z")

</div>

> [@WalterMadelim](#):
>
> `julia> sX = sX + [1 0; 0 1]`

The above code is equivalent to this

```julia
new_array = sX + [1 0; 0 1]
sX = new_array 

```

So you create and allocate a new array, and then you assign this new array to the variable `sX`. The old view that `sX` pointed to is gone.

If you want to _update_ the value that `sX` refers to instead, you write

```julia
sX .+= [1 0; 0 1]
# or
sX .+= I

```

The example in the OP is best handled with

```julia
sX .= rand.()

```

The distinction between assignment (`=`) and mutation (`.=`) is crucial.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [October 4, 2025, 11:57am UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/10 "2025-10-04T11:57:56Z")

</div>

> [@DNF](#):
>
> `sX .= rand.()`

I have difficulty understanding why is this syntax.

I can explain why it is not `sX .= rand()`, which is because `rand()` only once.

But I don’t understand why can you put that dot behind `rand` and before an empty `()`.

I don’t think this reads rational.

Is there a functional API for this that attains the same or better performance?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 4, 2025, 12:13pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/11 "2025-10-04T12:13:37Z")

</div>

It works because multiple dots in an expression fuse into a single broadcast call over all elements. For every element in `sX` there is a call to `rand`, which is directly input in the corresponding array position.

An alternative syntax is `rand!(sX)`, but that is not as general, since `sX .= f.()` will automatically work for _any_ function `f` (with a compatible return type), while `f!(sX)` would need to be implemented specially.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [October 4, 2025, 1:21pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/12 "2025-10-04T13:21:20Z")

</div>

Thanks, very useful! I’ve bookmarked this usage.

I still don’t understand why there isn’t a _functional_ API counterpart.  
I tried some methods which doesn’t produce good results in terms of performance

```julia
import Random.seed! as seed!
N = 9999

seed!(1);
a = -rand(N, N);
seed!(2);
@time @. a = rand(); # 0.103707 seconds

seed!(1);
a = -rand(N, N);
seed!(2);
@time broadcast!(_ -> rand(), a, a); # 0.160028 seconds (150.04 k allocations: 7.617 MiB, 42.89% compilation time)

seed!(1);
a = -rand(N, N);
seed!(2);
@time foreach(i -> setindex!(a, rand(), i), eachindex(a)); # 3.865129 seconds (199.97 M allocations: 2.980 GiB, 19.73% gc time, 0.30% compilation time)

```

> [@DNF](#):
>
> An alternative syntax is `rand!(sX)`, but that is not as general, since `sX .= f.()` will automatically work for _any_ function `f` (with a compatible return type), while `f!(sX)` would need to be implemented specially.

is the current `sX .= f.()` style (or `@. sX = f()`) very flexible then? I doubt this is something still to be determined.

My doubt is because, sometimes, I need to pass an address to an API:  
for example, the last arg `view(X, j)` here is an address

```julia
Gurobi.GRBgetdblattrelement(o, "X", 
        Gurobi.c_column(o, JuMP.index(x[j])),
        view(X, j))

```

in my this post [Efficiently Retrieving Variable Values after Gurobi optimization with JuMP - #23 by WalterMadelim](https://discourse.julialang.org/t/efficiently-retrieving-variable-values-after-gurobi-optimization-with-jump/127049/23).

In this circumstance I can’t figure out a way to use the highly efficient dot syntax.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 4, 2025, 3:55pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/13 "2025-10-04T15:55:08Z")

</div>

I am not able to understand the Jump syntax. Maybe you could give a more self-contained example of what you need?

I think some of your timing examples are down to suboptimal benchmarking. Take a look at BenchmarkTools.jl. I don’t think any of your code snippets would allocate if you benchmark correctly.

---

<div class="post-metadata">

**Author:** ![DanimirD](https://avatars.discourse-cdn.com/v4/letter/d/d2c977/32.png) [@DanimirD](https://discourse.julialang.org/u/DanimirD)\
**Post date:** [October 4, 2025, 4:48pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/14 "2025-10-04T16:48:09Z")

</div>

Thank you for the elaborate answer.

Yes, I do indeed expect a view to behave more like a reference.

And furthermore I expect it to be type stable.

This **is** Julia behavior btw:

```julia-auto
julia> sX::Int = 1
1

julia> sX += 7//3
ERROR: InexactError: Int64(10//3)

```

This is kind of what I would consider “good” behavior: Throw an error if the assignment to a “reference” is not possible with the given expression - and I would be fine with that; much more than with the actual behavior of views.

I don’t think that implicit copies and or/conversions of the “view”-type (or `SubArray`) are the intended behavior of a programmer who wants to avoid copies in the first place.

Thanks for the explanation, but in that case my conclusion is that views are very limited in their utility.

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [October 4, 2025, 5:11pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/15 "2025-10-04T17:11:44Z")

</div>

> [@DNF](#):
>
> I don’t think any of your code snippets would allocate if you benchmark correctly.

They indeed do not:

```julia-repl
julia> @btime @. $a = rand();
  119.171 ms (0 allocations: 0 bytes)

julia> @btime broadcast!(_ -> rand(), $a, $a);
  120.437 ms (0 allocations: 0 bytes)

julia> @btime foreach(i -> setindex!($a, rand(), i), eachindex($a));
  115.082 ms (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 4, 2025, 5:36pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/16 "2025-10-04T17:36:14Z")

</div>

> [@DanimirD](#):
>
> I don’t think that implicit copies and or/conversions of the “view”-type (or `SubArray`) are the intended behavior of a programmer who wants to avoid copies in the first place.
> 
> Thanks for the explanation, but in that case my conclusion is that views are very limited in their utility.

I’m pretty sure none of these things have anything to do with the behavior of views. Views are not converted to a different type, and you can easily use them without causing allocations.

It seems that you are are probably not that familiar with dynamically typed languages.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 4, 2025, 5:40pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/17 "2025-10-04T17:40:36Z")

</div>

> [@DanimirD](#):
>
> ```julia-auto
> julia> sX::Int = 1
> 1
> 
> julia> sX += 7//3
> ERROR: InexactError: Int64(10//3)
> 
> ```
> 
> This is kind of what I would consider “good” behavior: Throw an error if the assignment to a “reference” is not possible with the given expression

in this case you get an error message purely because the type annotation `::Int`, this code is still equivalent to:

```julia-auto
sX::Int = 1

temp = sX + 7//3

sX = temp

```

Which would translate to this for your original problem:

```julia-auto
julia> @views sX::SubArray = X[1:2,1:2];

julia> sX = rand(2,2)
ERROR: MethodError: Cannot `convert` an object of type
  Matrix{Float64} to an object of type
  SubArray

```

what you want is:

```julia-auto
julia> sX .= rand(2,2)
2×2 view(::Matrix{Float64}, 1:2, 1:2) with eltype Float64:
 0.491047 0.707516
 0.649978 0.503986

```

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [October 4, 2025, 6:09pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/18 "2025-10-04T18:09:27Z")

</div>

> [@jling](#):
>
> what you want is:
> 
> ```julia-auto
> julia> sX .= rand(2,2)
> 2×2 view(::Matrix{Float64}, 1:2, 1:2) with eltype Float64:
> 0.491047 0.707516
> 0.649978 0.503986
> 
> ```

or

```julia-auto
sX .= rand.()

```

or

```julia-auto
using Random
rand!(sX)

```

which don’t allocate extra memory.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [October 4, 2025, 9:09pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/19 "2025-10-04T21:09:40Z")

</div>

> [@DanimirD](#):
>
> Yes, I do indeed expect a view to behave more like a reference. And furthermore I expect it to be type stable.

> [@DanimirD](#):
>
> This is kind of what I would consider “good” behavior: Throw an error if the assignment to a “reference” is not possible with the given expression

I’m fairly convinced by now that you were and still are thinking of Julia variables as named values in statically typed languages.

1. Julia is not statically typed, it’s strictly dynamically typed.
2. Type stability is a practice to leverage the primary implementation’s type inference and compiler optimizations. Those are not language semantics, in fact the language can be implemented without type inference or a compiler (`JuliaInterpreter` does this to a large degree). Assignments definitely do not associate the value’s type with the variable; as I said before, this goes against the variable-object model.
3. Loosely speaking, a view or a variable can be called “references”, but they are not referring to values the same way, and definitely not the same way as language-level pointers or references in other languages. The primary implementation of Julia has a core in C so there are memory addresses in some objects, but pointers don’t exist on the _Julia_ language level. It’s not possible to exactly translate such semantics from another language to Julia.

> [@DanimirD](#):
>
> `sX::Int = 1`

Despite how this looks, this isn’t static typing nor is it making any part of the value part of the variable’s characteristics. In fact, you can declare a type for the variable without assigning/defining it, though you wouldn’t want to access it until it has been:

```julia-auto
julia> global y::Int

julia> y
ERROR: UndefVarError: `y` not defined in `Main`
Suggestion: add an appropriate import or assignment. This global was declared but not assigned.

```

The declared type doesn’t have to exactly match the assigned value’s type either. Type declarations on variables add type checks to the assignment and try to `convert` the value to the type (on the language level, but the compiler can optimize this away). So, an abstract type for the variable is perfectly compatible with values of concrete _subtypes_, and the value’s type selects methods.

```julia-auto
julia> z::Number = 1
1

julia> typeof(z)
Int64

julia> foo(::Int) = "hello";

julia> foo(::Number) = "goodbye";

julia> foo(z)
"hello"

```

> [@DanimirD](#):
>
> I don’t think that implicit copies and or/conversions of the “view”-type (or `SubArray`) are the intended behavior of a programmer who wants to avoid copies in the first place.

Then don’t write the operations that the language specifies to do so. This isn’t a language where `+=` has a separate “in-place” implementation from `+`, `a += b` literally means `a = a + b`. Sure, the compiler optimizes to in-place operations for some ubiquitous primitive types like `i += 1` incrementing an integer, but that’s irrelevant on the _language level._ So, `sX += I(2)` just means assigning `sX + I(2)` to `sX`. Adding a `SubArray` and `Diagonal` requires promotion to a compatible output type in any language, and like the explanation in my previous comment, the view is also uninvolved in this reassignment to the output `Matrix`. If you want in-place addition to the view assigned to `sX` instead of reassigning `sX`, then you have to write `sX[:,:] += I(2)` or `sX .+= I(2)` to specify the view’s elements. There’s no way around that, that’s just how this language works.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [October 4, 2025, 11:46pm UTC](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869/20 "2025-10-04T23:46:55Z")

</div>

I feel somewhat strange to add a `$` at the left-hand-side of a `=`.  
Despite this, there is still one difference:

In my original example, the three `a` outcomes are _identical_. Meaning that the three methods are from the same starting point and attains the same destination.

But with your `@btime` they _don’t_. Due to sample number? I don’t know.

* * *

Edit: Okay I’ve sorted it out 😊

```julia
import Random.seed! as seed!
using BenchmarkTools
function get_starting_a()
    seed!(1);
    -rand(N, N);
end;

julia> N, S, E = 999, 98, 99;

julia> a = get_starting_a(); seed!(2);

julia> @btime(foreach(i -> setindex!($a, rand(), i), eachindex($a)); samples=S, evals = E);
  930.328 μs (0 allocations: 0 bytes)

julia> a = get_starting_a(); seed!(2);

julia> @btime(@. $a = rand(); samples=S, evals = E);
  951.779 μs (0 allocations: 0 bytes)

julia> a = get_starting_a(); seed!(2);

julia> @btime(broadcast!(_ -> rand(), $a, $a); samples=S, evals = E);
  900.982 μs (0 allocations: 0 bytes)

```

It’s indeed surprising that now `@.` is the slowest🙃

[Next page](https://discourse.julialang.org/t/assigning-to-a-view-of-an-array/132869.md?page=2)
