# Why is it that Arrays can't be modified using nested index

**URL:** https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889
**Category:** General Usage
**Created:** [February 1, 2023, 9:36pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889 "2023-02-01T21:36:13Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)
#### Post date: [February 1, 2023, 9:36pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/1 "2023-02-01T21:36:13Z")

</div>

In this expression

```julia
A = ones(3,3);
# this works
A[1,1] = 2;

julia> A
3×3 Matrix{Float64}:
 2.0 1.0 1.0
 1.0 1.0 1.0
 1.0 1.0 1.0

# but this does not
A[:,1][1] = 3;

julia> A
3×3 Matrix{Float64}:
 2.0 1.0 1.0
 1.0 1.0 1.0
 1.0 1.0 1.0

```

why is `A` not modified in this instance? I realize that `A[:,1]` is creating a copy of `A[:,1]` and then I’m indexing into that copy, for instance I can get it to work by specifying `view(A[:,1])`

```julia
@view(A[:,1])[1] = 3;

julia> A
3×3 Matrix{Float64}:
 3.0 1.0 1.0
 1.0 1.0 1.0
 1.0 1.0 1.0

```

What I don’t get is why julia is unable to recognize that the user would like to modify `A`, is there any ambiguity that this is what the user would like to do? Having to use `view` seems unintuitive.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [February 1, 2023, 10:01pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/2 "2023-02-01T22:01:17Z")

</div>

The tldr is that the decision to make `A[:, 1]` a copy rather than a view was made back in 0.6 and was made due to the cost of views in 0.6 that was largely removed in 1.5 due to a smarter compiler. If we were making the choice today, we probably would do it differently.

---

<div class="post-metadata">

### Author: ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)
#### Post date: [February 1, 2023, 10:31pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/3 "2023-02-01T22:31:03Z")

</div>

That’s unfortunate, would this be something that could be fixed in 2.0 or is it just too big of change now?

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [February 1, 2023, 10:35pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/4 "2023-02-01T22:35:18Z")

</div>

This would be on the very edge of fixable in 2.0, but it would be a really big change.

---

<div class="post-metadata">

### Author: ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)
#### Post date: [February 1, 2023, 11:31pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/5 "2023-02-01T23:31:19Z")

</div>

There are a number of issues and PRs related to views/copies, you can e.g. start at [range indexing should produce a subarray, not a copy · Issue #3701 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/3701#issuecomment-311119025).

Another aspect of this is that

```julia
A[:,1][1] = 3

```

lowers to

```julia
setindex!(getindex(A, :, 1), 3, 1)

```

and at that point the intent is not really visible any more (as the `getindex` call is evaluated before `setindex` gets called).

---

<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: [February 1, 2023, 11:32pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/6 "2023-02-01T23:32:25Z")

</div>

> [@alex-s-gardner](#):
>
> What I don’t get is why julia is unable to recognize that the user would like to modify `A`, is there any ambiguity that this is what the user would like to do? Having to use `view` seems unintuitive.

I think it’s pretty risky to go down the path of breaking the rules of how the language works and try to second-guess the user: “You wrote _this_, but _probably_ meant something else. Let me fix that, quietly, behind your back.”

For those who know that slices make copies, it would be _very_ unintuitive to see that happen.

---

<div class="post-metadata">

### Author: ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)
#### Post date: [February 2, 2023, 4:44pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/7 "2023-02-02T16:44:24Z")

</div>

I guess my point in this case is that from a purely syntax perspective what the user wants is not ambiguous… there is no guessing needed. If the nested index appears on the left hand side of the `=` then user is trying to modify the variable on the left hand side. Is there a case where this break?

---

<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: [February 2, 2023, 4:53pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/8 "2023-02-02T16:53:48Z")

</div>

It could be for testing purposes or experimentation or demonstration. I don’t know.

But I think the suggestion is a really bad principle to follow, twisting or even outright changing the meaning of the code in order to guess what is ‘really meant’. I would guess it makes work harder for the compiler too, and as far as I understand it also breaks [referential transparency](https://en.wikipedia.org/wiki/Referential_transparency).

And it feels super weird and dangerous. How are you going to be able to look at code and reason about what it does, when basic rules are broken like that?

In cases like this, you should get help to fix the code, for example by a linter, not have the code secretly fixed for you.

---

<div class="post-metadata">

### Author: ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)
#### Post date: [February 8, 2023, 4:57pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/9 "2023-02-08T16:57:28Z")

</div>

I can’t help but think that having a rule that states that all indexing on the left hand side of an equals sign is a view rather than a copy would be a significant benefit:

```julia
a = [[1,2],[3,4], [5,6]];
a[1][1] = 0;

julia> a
3-element Vector{Vector{Int64}}:
 [0, 2]
 [3, 4]
 [5, 6]

```

```julia
a = [1 2; 3 4; 5 6]
a[:,1][1] = 0;

julia>a
3×2 Matrix{Int64}:
 1 2
 3 4
 5 6

```

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [February 8, 2023, 5:09pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/10 "2023-02-08T17:09:38Z")

</div>

What does work at present is using `@views` in front of the expression, which ensures that all indexing happens in-place

Edit: this is not adding anything new

---

<div class="post-metadata">

### Author: ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)
#### Post date: [February 8, 2023, 10:18pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/11 "2023-02-08T22:18:32Z")

</div>

> [@DNF](#):
>
> “You wrote _this_, but _probably_ meant something else. Let me fix that, quietly, behind your back.”

Implicitly creating a copy instead of a subarray view seems to fit this description.

---

<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: [February 9, 2023, 6:13am UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/12 "2023-02-09T06:13:36Z")

</div>

> [@uniment](#):
>
> Implicitly creating a copy instead of a subarray view seems to fit this description.

I’m sorry, can you explain? Did you mean “explicitly and consistently with how `getindex` works, as described in the documentation”?

It’s not that I think the current behavior is fantastically useful, but it’s logically consistent.

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [February 9, 2023, 7:00am UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/13 "2023-02-09T07:00:59Z")

</div>

> [@DNF](#):
>
> twisting or even outright changing the meaning of the code in order to guess what is ‘really meant’.

I’d not put things in such strong terms. This sounds more like a set of rules, where indexing on the left-hand side is always wrapped in `@views`. Currently, a view is created in certain cases while not in others, e.g.

```julia
a[:,1] .= 2

```

will not compute `a[:,1]` and then overwrite it with `2`, rather it will compute `@view(a[:,1])` and overwrite it with `2`. In your words, this is already trying to guess what is really meant, rather than being consistent in how getindex works. That’s because this is lowered to `dotview`, and not `getindex`:

```julia
julia> Meta.@lower a[:,1] .= 2
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ %1 = Base.dotview(a, :, 1)
│ %2 = Base.broadcasted(Base.identity, 2)
│ %3 = Base.materialize!(%1, %2)
└── return %3
))))

```

This isn’t obvious at all from the 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: [February 9, 2023, 7:45am UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/14 "2023-02-09T07:45:37Z")

</div>

> [@jishnub](#):
>
> `a[:,1] .= 2`

I’ve always read this as a `setindex!` expression, nothing to do with views, so I’m a bit surprised to see that the above is implemented in terms of view.

> [@jishnub](#):
>
> I’d not put things in such strong terms.

The wording is probably due to what I interpreted as the logic behind the proposal: Let’s break the rules whenever we think the intention of the code is something other than what is written.

Discussing if `setindex!` should, for example, handle nested indices, on the other hand, is less problematic.

---

<div class="post-metadata">

### Author: ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)
#### Post date: [February 9, 2023, 9:15am UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/15 "2023-02-09T09:15:36Z")

</div>

> [@DNF](#):
>
> can you explain?

Sorry, perhaps I shouldn’t have used the word “implicitly,” as ultimately whether something fits that descriptor is a function of whether it’s documented—which this is.

Putting myself back in the shoes of someone freshly learning this aspect of the language, though, it’s not clear that accessing a slice should create a copy. Infact, it’s counterintuitive because it seems inconsistent.

Namely, `getindex` on a slice creates a copy, while `setindex!` (quite obviously) doesn’t. While this is straightforward when you consider the lowered code, from the syntax it’s less clear. From the syntax, it’s reasonable to believe slicing on the LHS of `=` simply doesn’t create copies while on the RHS it does. For the appropriate response to a newbie to be, “Well, first you must understand what this lowers to” is mildly frustrating, because we don’t interact with the lowered code—we interact with the syntax. (and why should an economist or a biologist have to know what lowering is, anyway?) What would have created a stronger sense of consistency would be if _neither_ creates a copy, and _both_ access slices of the array itself, so that nothing would seem different about appearing on the LHS vs. the RHS.

It seems as if the most direct way to resolve this inconsistency would be to make all sliced `getindex` calls return views, and to require copying to be performed by explicit calls to `copy`, as proposed in [#3701](https://github.com/JuliaLang/julia/issues/3701). If that decision had been made, probably many aspects of the language would be quite different, and ripping the bandaid off now will be twenty times more painful than back then. Of course, it’s easy for me to Monday morning quarterback a decade after the fact; I’m sure there were hundreds of other considerations at play back then that have changed by now.

---

<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: [February 9, 2023, 11:40am UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/16 "2023-02-09T11:40:36Z")

</div>

> [@uniment](#):
>
> What would have created a stronger sense of consistency would be if _neither_ creates a copy, and _both_ access slices of the array itself, so that nothing would seem different about appearing on the LHS vs. the RHS.

Agree with this. It’s probably just too late.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [February 9, 2023, 5:01pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/17 "2023-02-09T17:01:44Z")

</div>

> [@jishnub](#):
>
> will not compute `a[:,1]` and then overwrite it with `2`, rather it will compute `@view(a[:,1])` and overwrite it with `2`.

The fact that this uses internal machinery that with the name `view` in it is entirely beside the point. The basic idea all stems from the concept that `a[...] = x` will modify `a` and not the object stored at `a[...]`.

---

<div class="post-metadata">

### Author: ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)
#### Post date: [February 9, 2023, 9:04pm UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/18 "2023-02-09T21:04:21Z")

</div>

The most frustrating optima are those that we know about, but are just out of reach 😅

Many people have brought up the possibility of view-slicing arrays for 2.0, but it seems increasingly unreachable. The possibility of full-Julia arrays has also been raised many times. Maybe if the two ideas are merged—make the full-Julia arrays view-slicing so that that becomes the preferred idiom—the transition to view-slicing arrays in 2.0 can be easier.

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [February 10, 2023, 5:10am UTC](https://discourse.julialang.org/t/why-is-it-that-arrays-cant-be-modified-using-nested-index/93889/19 "2023-02-10T05:10:08Z")

</div>

Thanks, the rules are certainly clear and consistent. The confusion stems from the fact that `a[:,:][1] = 3` is a compound `getindex`+`setindex!` operation, which makes this out-of-place. In an operation like this, one may split this into two statements:

```julia
b = a[:,:];
b[1] = 3

```

However, this is not what one may do in a `setindex!`, despite the superficial similarity in syntax:

```julia
a[:] .= 3

```

is not the same as

```julia
b = a[:]
b .= 3

```

There is no contradiction here, just some getting-used-to.
