Julia: Warn that double-indexed assignment does nothing

Created on 26 Sep 2019  路  10Comments  路  Source: JuliaLang/julia

Emit a warning or error if the user attempts to make a double-indexed assignemnt:

b = [1;4;5;6;7]
b[2:3][1] = 10
b[2:3][1] == 4 # true

Appears this was discussed in #119 as a feature, suggesting I'm not the only one who thinks to try it. As this is a no-op, would be useful to explicitly state it isn't supported, with a hint of how to achieve the intended behavior.

doc

Most helpful comment

That said, I am sympathetic to the argument that slices should be immutable by default, in which case this would be an error, but that's a bit of a separate discussion and requires some infrastructure we do not have yet.

All 10 comments

It does something, just not what you expect. If you can find a good place to put it in the manual, a PR to note this would be helpful.

Okay. What's the use for it?

It indexes into a collection of collections rather than a multi dimensional collection.

I'm not sure I understand.

If b::Vector{Vector{Any}}

b[1][2] would index into the second element of the first vector.

b[2:3][2] however is equivalent to b[3]

This is because b[2:3] is an array they you are asking for the 2nd element of. You probably meant b[2:3].[2]

@oscardssmith - No, I didn't. That's invalid syntax. I'm asking about assigning a value to b[2:3][2].

The reason we can't give a warning is that it's valid syntax that could mean something, it's just not what you meant it to mean. However, we can't assume that that's the case for all values of b and we don't have access to types at the syntactic level to give more specific error messages. As a trivial example, consider:

struct Foo; end
Base.getindex(x::Foo, args...) = x
Base.setindex!(x::Foo, args...) = println("Hello")
julia> b[2:3][1] = 10
Hello
10

That's a perfectly sensible and consistent result, so we can't just give a syntax warning for it.

That said, I am sympathetic to the argument that slices should be immutable by default, in which case this would be an error, but that's a bit of a separate discussion and requires some infrastructure we do not have yet.

This is not double-indexed assignment. It is creating an array (via slicing) and copying a value to an element of that array.
This kind of question arises frequently because people expect slices to create a view rather than a copy. That may be what is happening here. (Better documentation might help.) Furthermore, I don't see how to make slices immutable without changing the semantics of slicing. A slice (the method defined for getindex(A::Array, I::UnitRange{Int})) creates a copy of part of A as an Array, and Arrays are mutable:

julia> b = [1;4;5;6;7];

julia> c = b[2:3]; typeof(c)
Array{Int64,1}

julia> c[1] = 1
1

julia> c
2-element Array{Int64,1}:
 1
 5

I think what the OP wants is this

julia> b = [1;4;5;6;7];

julia> @views b[2:3][1] = 10
10

julia> print(b)
[1, 10, 5, 6, 7]

Btw. Keno's example is missing the line b = Foo(). It illustrates that the semantics of slicing is determined by the choice of methods for getindex and setindex on particular types, not by syntax.

Yes, thanks @jlapeyre. "Views" aren't something I've gotten used to yet.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

StefanKarpinski picture StefanKarpinski  路  138Comments

stevengj picture stevengj  路  174Comments

StefanKarpinski picture StefanKarpinski  路  113Comments

StefanKarpinski picture StefanKarpinski  路  216Comments

StefanKarpinski picture StefanKarpinski  路  249Comments