-
Notifications
You must be signed in to change notification settings - Fork 149
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
Inconsistencies with multi-argument constructors #518
Comments
Right. From a user perspective, we tend to make available the "varargs list of elements" constructor, like Do you know what the current best practice is for array constructors vs |
The common case here is to The main place I've used So IMO we should just deprecate the special |
I don't think this is a We have the "varargs list of elements" constructor on purpose. I particularly don't like special cases where certain lengths (typically 0 or 1) don't follow the overall pattern. Currently, this seems odd to me: julia> SVector(1:3)
ERROR: UndefVarError: S not defined
Stacktrace:
[1] Size(::Type{SArray{Tuple{S},T,1,S} where T where S}) at /home/ferris/.julia/dev/StaticArrays/src/traits.jl:86
[2] length(::Type{SArray{Tuple{S},T,1,S} where T where S}) at /home/ferris/.julia/dev/StaticArrays/src/abstractarray.jl:2
[3] convert(::Type{SArray{Tuple{S},T,1,S} where T where S}, ::UnitRange{Int64}) at /home/ferris/.julia/dev/StaticArrays/src/convert.jl:20
[4] SArray{Tuple{S},T,1,S} where T where S(::UnitRange{Int64}) at /home/ferris/.julia/dev/StaticArrays/src/convert.jl:5
[5] top-level scope at none:0
julia> SVector(1:3, 1:3)
2-element SArray{Tuple{2},UnitRange{Int64},1,2}:
1:3
1:3
julia> SVector(1:3, 1:3, 1:3)
3-element SArray{Tuple{3},UnitRange{Int64},1,3}:
1:3
1:3
1:3 If we want to support If we drop the 2nd and 3rd from the above, we lose our nice constructors :( If we do nothing the situation is confusing. I feel a bit stuck between a rock and a hard place. Any ideas? |
So according to that progression, If one wants So if we say that On the other hand, for It's definitely tricky. It would arguably be most consistent to remove the constructors like |
Oh, and also go through a proper deprecation cycle of course. |
Mind-reading is so easy when the only types ever living in a container are I think it's most important to retain consistency with Base, even if arguably Base's behavior is wrong. SVector(1:3) == [1, 2, 3]
SVector((1:3,)) == [1:3]
SVector(1, 2, 3) -> depwarn
SVector((1,2,3)) == [1,2,3]
SVector(((1,2,3),)) == [(1,2,3)]
Scalar([1]) -> depwarn
Scalar(([1],)) gives a 0-dim array Am I missing important cases? |
To be clear what's on my mind at the moment, I am seriously thinking of following the OP in JuliaLang/julia#29350 (except for arrays, not numbers) and dropping I think the arguments are basically the same as in that issue:
|
Sorry @timholy I spent so long writing my post that I missed yours. I guess my question to you is this: is the error in
Yes, it's true that we've generally been pretty religious about following the semantics of I'm still left with this thought: To me, the priority of consistency would go towards the language itself over its |
@andyferris ok good argument. I can see it would work pretty cleanly to just write |
I recognize a lot of merit in the distinctions you're making @andyferris. Just be careful about writing StaticArrays according to an imagined Julia 2.0 and forcing that way of thinking on your users, when Julia 2.0 is hopefully at least 5 years away. That's a long time to maintain a disconnect between Base and the way this package works. |
But does |
Yes it does, because SubArray requires extra arguments. Consider PaddedViews: can you build one without specifying the pad value? No, and that's wonderful. Therefore this is not a problem. |
I think the point is that if I take seriously what you are saying about fracturing the interface - but I'm not sure either of the two options you present in the OP would do that, would it? I mean, are all abstract arrays meant to follow (And yes, the broader strokes of my arguments above can't be implemented willy-nilly straight away).
Is this meaning: it's OK for (Sorry for all the questions, Tim!) |
(Not that I think I have definitive answers, just opinions.) In my view errors are nothing to worry about, but magic is. You're arguing, with a great deal of merit, that there's too much magic right now. I agree, but given that Again, I'm sympathetic with this: heck, I raised a variant of this back in 2012, one of the very few times I've ever used "wart" in conjunction with Julia. But any sufficiently complicated system is going to have warts. I'm just arguing this package---because it is clearly designed to be an adjunct on Base---should choose to have the same warts. That's all. So I am basically advocating #518 (comment) as a solution. Unless I've missed important cases, that is. |
Thanks Tim for your insights, you've given me much to think about. On a practical level, I do have concerns about
since it seems highly disruptive (and is basically the only way I use this package). We could, for instance, completely punt in the case of one-argument constructors, since not many people use length-1 static arrays. But then again, I was asked to properly support length-0 static arrays... so I suspect this may upset someone... |
What's wrong with |
Extra typing, I guess? (See #24 - people have argued hard to reduce the current typing) Really, I want something as compact as My take on The |
Right, for people doing geometry with this package (which was the original reason for creating it) a compact readable literal notation is a big deal. For these people the |
The discoverability of |
I think this issue is the main conundrum which has been holding up release of StaticArrays 1.0. I had another think about this while reviewing over at #626 (review) and had some thoughts. A proposal:
Example usage: @SA(1) # Construct 0-dimesional `SArray`
@SA[1,2] # Constructor SVector{2,Int}
@SA[1 2; # Construct SMatrix{2,2,Int}
3 4]
@SA Float64[1 2; # Construct SMatrix{2,2,Float64}
3 4]
# Use in an expression was greatly improved by https://github.com/JuliaLang/julia/pull/23547
# (note lack of space between `@SA` and `[`
@SA[1,2,3] .+ 1
# For constructing other StaticArray subtypes, recommend composition via conversion, rather than
# defining a zoo of macros `@MMatrix`, `@MVector` etc etc.
MMatrix(@SA[1 2;
3 4])
# For example, from issue #626, a 3x3 stress tensor
Stress(@SA[1 2 3;
4 5 6;
7 8 9]) For |
Scalar
and conversion vs wrap
Ok, I've added #633 as one possible alternative syntax for constructors. Thinking about this for StaticArrays-1.0, I do think Tim's proposal in #518 (comment) is extremely consistent. A staged approach to this would be to pursue a convenient literal syntax like #633 (or equivalent alternative), and see how it pans out in the StaticArrays-1.x release series. If it works out well, we can consider dropping the multi-argument constructors at a later date. I guess I'm still not sure that a rush for consistency is worth the potential breakage of a lot of practical code. At least staging the deprecation this way will allow people a lot of time to adjust, and providing an even more convenient syntax will give them an incentive 😃 |
Given that
Scalar <: SArray
, the behavior ofStaticArrays.jl/src/Scalar.jl
Line 10 in 552bc75
is inconsistent with
StaticArrays.jl/src/convert.jl
Line 5 in 552bc75
Fortunately, in a few cases there's a very welcome ambiguity error:
but mostly this just silently does things differently for 0 dimensions than for any other dimension.
I don't think you can really have both. Can you choose which behavior you want to keep?
The text was updated successfully, but these errors were encountered: