-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More specific characterization of mutable collections with can_setindex
and can_change_size
#46500
base: master
Are you sure you want to change the base?
Conversation
…dex` and `can_change_size`
I think that some tests / traits for such properties would be valuable. And the reason to have them in Base is to make extending them frictionless. But they need to be handled more carefully than this PR does.
The rough idea is clear, it's to distinguish things like Vector from things like SVector & UnitRange. But what exactly does "may change size" mean?
julia> v = [1,2,3,4]; m = reshape(v, 2,2); pop!(v) # Vector{Int} is not enough
ERROR: cannot resize array with shared data Alternatively,
Returning (And why say "change size" not length, given that it accepts non-array collections, and
Again, the rough idea is clear, but what exactly does
Some are safe, some aren't. What's envisaged for Can what's desired be known from the type or does it needs an instance, and the proposed indices? It might want to be a close cousin of julia> x = Bidiagonal([1,2,3], [4,5], :L)
3×3 Bidiagonal{Int64, Vector{Int64}}:
1 ⋅ ⋅
4 2 ⋅
⋅ 5 3
julia> x[2,1] = 10; # this is OK, but typeof(x) doesn't know about :L
julia> x[1,2] = 10
ERROR: ArgumentError: cannot set entry (1, 2) off the lower bidiagonal band to a nonzero value (10)
julia> checkbounds(Bool, x, 1, 3) # tells you about getindex
true
julia> d = Dict(1=>:A, 2=>:B);
julia> d[1:2] = [:C, :D] # only some kinds of `setindex!` work here
ERROR: MethodError: Cannot `convert` an object of type UnitRange{Int64} to an object of type Int64
julia> Base.setindex((:a, :b, :c), :Z, 3) # can setindex, just not setindex!
(:a, :b, :Z) |
Note that the name suggests the question is about |
@mcabbott, it might be of interest to see the original issue that preceded these being implemented in ArrayInterface (JuliaArrays/ArrayInterface.jl#22). The original intention was to pass types so that this information would be known at compile time. It seems there are very few situations where this could return |
I'd propose Try.jl-style |
Even TryExperimental.jl still uses traits like |
The point of Try.jl is to redesign the APIs so that there is no try/catch at all: failure doesn't throw, it returns |
That still requires doing a try catch block internally on methods that don't have relevant trait. If anything these methods would support creating the type of API you want. |
My worry is that |
|
I may be missing something because I don't see how this is any different from adding any trait to base that might be a branch point. We try to choose the safest default and the ability of downstream methods working correctly depends on adherence to the trait method. The alternative is to delay improving the situation at all until Julia v2 where we can redefine indexing interfaces. All interfaces that accomplish what you're aiming for require some degree of additional traits (internally or externally). BangBang.jl also has to implement its own variant of checking index mutability traits to accomplish this.
Sounds good to me. We could also imitate the syntax for |
This implements
can_setindex
andcan_change_size
, which provide more clear information that is related toismutable
but isn't necessarily the same.Knowing that the length can change may invalidate bounds checking assumptions and collections that can use
setindex!
aren't threadsafe (#41214, #40096).Helpful for making optionally mutating operations generic (#30407).
Sometimes we have a type where we want to disallow these mutating behaviors even if there is somehow generic support for them.