-
Notifications
You must be signed in to change notification settings - Fork 18
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
Encode bound information as type parameter #102
Conversation
Documentation is currently causing test failures |
I would suggest making them singleton struct types instead of symbols, since I think they're easier for the compiler to optimize out. Plus then you could have: abstract type Endpoint end
abstract type Bounded <: Endpoint end
struct Unbounded <: Endpoint end
struct Open <: Bounded end
struct Closed <: Bounded end and then we could define methods which only work on bounded intervals more cleanly. We could also have: struct AnchoredInterval{P, T, L, R} where {L<:Bounded, R<:Bounded} <: AbstractInterval{T, L, R} |
I like this overall. It's nice to be able to say Plus it seems unlikely that you'll want to store packed arrays with different inclusivities, which is the thing you need to worry about when adding type parameters. |
I can give this a try again. In a previous incarnation I wanted to do this and also use symbols in constructors as a convenient syntax but I ran into some issues. I filed an issue on this: JuliaLang/julia#36213 |
Codecov Report
@@ Coverage Diff @@
## master #102 +/- ##
===========================================
- Coverage 96.25% 69.94% -26.31%
===========================================
Files 8 8
Lines 267 376 +109
===========================================
+ Hits 257 263 +6
- Misses 10 113 +103
Continue to review full report at Codecov.
|
I commented on that issue. I don't think your use of type parameters there was sound. |
Is there any reason to have some singletons as |
Making them |
It also means we can instantiate them, which can be easier for passing and dispatching on argument types. All traits in base Julia are like that. |
It seems a little wonky to me to be able to write |
I should note that abstract type Bound end
struct Open <: Bound end
struct Closed <: Bound end When including abstract type Bound end
abstract type Bounded <: Bound end
struct Unbounded <: Bound
struct Open <: Bounded end
struct Closed <: Bounded end I think I'd probably leave out |
I should also point out that IntervalSets.jl uses |
As the response to this proposed change has been positive I'll complete the remainder of the work:
|
91939f4
to
11f70ed
Compare
PR should now be complete and can be reviewed at this time. I'll call out the couple of minor negative points to do with this change:
|
end | ||
|
||
function Base.convert(::Type{Interval{T}}, interval::AnchoredInterval{P, T}) where {P, T} | ||
return Interval{T}(first(interval), last(interval), inclusivity(interval)) | ||
function Base.convert(::Type{Interval{T}}, interval::AnchoredInterval{P,T,L,R}) where {P,T,L,R} |
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.
Is there a situation where this function is used over the one above? or more so, would there ever be a difference?
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.
The signatures of these two functions is identical with the updated AnchoredInterval
type.
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.
Do we need them both then?
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.
I misinterpreted your original question. The actual answer to your initial question is that there is a difference between the two functions. One is called as convert(Interval, ...)
which is just "convert this to a subtype of Interval" where convert(Interval{Int64}, ...)
is "convert this to a subtype of Interval
where the element type is Int64
".
We could combine these so the signature is:
Base.convert(::Union{Type{Interval}, Type{Interval{T}}, ...)
I may make that change in another PR.
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.
I think this is just me trying to wrap my head around multiple dispatch for certain things. I get that one is just strictly Interval
and the other is Interval{T}
, but doesn't the Interval{T}
one stipulate that the T
has to be the same type as the T
in the AnchoredInterval{P,T,L,R}
?, and therefore you wouldn't be able to do something like convert(Interval{Float64})
if the T
in the AnchoredInterval
was an Int64
per se? Perhaps I am misunderstanding, and both T
's don't actually need to match?
🤷 Different issue, but |
88f26f6
to
70443cb
Compare
Just applied Fernando's change and corrected the doctests |
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.
LGTM
70443cb
to
a59deb6
Compare
a59deb6
to
f24a406
Compare
When updating the Intervals.jl to support unbounded ranges I encoutered an issue where the interface we had made it difficult to define unbounded ranges. For example if we update
Inclusivity
to have unbounded fields then constructor would take 4 bools: left open/closed, right open/closed, left unbounded, right unbounded:(Aside: note we still store a value for the unbounded side as we want
Interval
to be a bits type. The value here ultimately is ignored as it is unbounded)This interface isn't very intuitive and needs some revision. While looking into reducing storage size of intervals I discovered that we can reduce the size of an interval in memory by having the bound information encoded in the the type parameters. The clearest way to do this is to use symbols. Using the same example as above we could have:
With the option to alternatively construct the same interval with in the future:
This PR currently implements minimal working changes that support encoding bound information as type parameters. At this point there is no support for unbounded ranges. If we like this interface I can update the remainder of the code. If we don't like this I could work on an alternative interface such as: