-
-
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
Make arrays and ranges hash and compare equal #16401
Changes from all commits
abc8d5b
c02f66a
a0a44b8
1a67101
9d18a7a
34c3239
82d6b5e
6ef5b92
0f00a22
b747330
bba5070
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,3 +20,40 @@ TypeArithmetic(instance) = TypeArithmetic(typeof(instance)) | |
TypeArithmetic(::Type{<:AbstractFloat}) = ArithmeticRounds() | ||
TypeArithmetic(::Type{<:Integer}) = ArithmeticOverflows() | ||
TypeArithmetic(::Type{<:Any}) = ArithmeticUnknown() | ||
|
||
# trait for objects that support ranges with regular step | ||
""" | ||
TypeRangeStep(instance) | ||
TypeRangeStep(T::Type) | ||
|
||
Indicate whether an instance or a type supports constructing a range with | ||
a perfectly regular step or not. A regular step means that | ||
[`step`](@ref) will always be exactly equal to the difference between two | ||
subsequent elements in a range, i.e. for a range `r::AbstractRange{T}`: | ||
```julia | ||
all(diff(r) .== step(r)) | ||
``` | ||
|
||
When a type `T` always leads to ranges with regular steps, it should | ||
define the following method: | ||
```julia | ||
Base.TypeRangeStep(::Type{<:AbstractRange{<:T}}) = Base.RangeStepRegular() | ||
``` | ||
This will allow [`hash`](@ref) to use an O(1) algorithm for `AbstractRange{T}` | ||
objects instead of the default O(N) algorithm (with N the length of the range). | ||
|
||
In some cases, whether the step will be regular depends not only on the | ||
element type `T`, but also on the type of the step `S`. In that case, more | ||
specific methods should be defined: | ||
```julia | ||
Base.TypeRangeStep(::Type{<:OrdinalRange{<:T, <:S}}) = Base.RangeStepRegular() | ||
``` | ||
|
||
By default, all range types are assumed to be `RangeStepIrregular`, except | ||
ranges with an element type which is a subtype of `Integer`. | ||
""" | ||
abstract type TypeRangeStep end | ||
struct RangeStepRegular <: TypeRangeStep end # range with regular step | ||
struct RangeStepIrregular <: TypeRangeStep end # range with rounding error | ||
|
||
TypeRangeStep(instance) = TypeRangeStep(typeof(instance)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we put in an error for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think that's necessary since that method is only called by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about package authors defining custom range types, or element types that go into ranges? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only situation in which package authors would need this would be if they define a new range type for which neither the O(N) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these aren't exported, but should they go in the stdlib? are the other traits in this file there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. The other traits are not exported, but I'm not sure what their use outside of Base is. @timholy?
The traits could also be mentioned somewhere in the manual, but I'm not sure where. They could go to the Interfaces section, but they aren't related to any existing interface (except maybe
Real
). Maybe we could have a sub-section listing all traits that a custom type may want to implement: this trait will generally be useful when you write your own type.