IntervalSets.jl
IntervalSets.jl copied to clipboard
Alternative to specify open/closed endpoints
In AcceleratedArrays.jl I've been playing with "search intervals" for querying data, for example finding all the dates within a given range with the help of a sort-based acceleration index.
To accommodate open and closed intervals, I've been toying with the idea of syntax that looks like a..exclude(b)
, which would be closed on the lower bound and open on the upper bound. exclude(b)
creates an Exclude
object which slightly redefines isequal
and isless
. See this file, particularly near the bottom.
Basically, I wonder if we've got our bananas turned inside out and whether it would be simpler/more composible to make this a property of the elements (endpoints) of the interval rather than of the interval itself?
Exclude
doesn’t have any mathematical meaning that I can think of...
Right... I was thinking that you technically may need something like infinitesimally_larger_than(start) .. infinitesimally_smaller_than(stop)
. These define the previous (or next) value acording to the (isequal, isless)
total ordering. (They don't have to be the same Julia type as start
or stop
).
I guess it was my feeling that such an interface might be simpler for users and simpler in implementation - it's just the composition of a small number of very simple concepts, rather than having a variety of different interval types and a larger set of interval-reflection functions, etc.
The simplest implementation is always the one that’s already been done...
I can see some benefits of your suggestion, but implementation wise it would require having 3 templates variables: the left endpoint type, the right endpoint type, and the domain type. This might turn into a headache.
If it’s the user facing syntax that’s wanted, that’s easy to add:
..(a::Exclude, b::Exclude) = OpenInterval(a,b)
PS I’d prefer a swift like syntax a ..< b
but that requires parser changes.
I'm not currently convinced you need a domain type. You can simply trust isless
and isequal
to sort out their own promotions for in
, etc.
If it’s the user facing syntax that’s wanted, that’s easy to add
Right, that's true!
PS I’d prefer a swift like syntax
a ..< b
but that requires parser changes.
Something like this would be pretty sweet. Alternatively, a unary op for "infinitesimally smaller than" could do a similar thing and be visually similar, I guess.
In SingularIntegralEquations.jl I use the following 1⁻
/1⁺
and (x)⁻
/(x)⁺
. This is possible using something like:
struct Exclude{S,T}
x::T
end
Exclude{S}(x::T) where {S,T} = Exclude{S,T}(x)
const ⁺ = Exclude{true}(true)
const ⁻ = Exclude{false}(true)
*(a::Number, b::Exclude{S}) where S = Exclude{S}(a*b.x)
Here's a Haskell package that puts the open- / closed-ness into the bounds. It also has syntactical sugar for creating intervals similar to that suggested above: a <..< b
, a <=..< b
, a <..<= b
, a <=..<= b
. It could be a good reference for design / API questions like this.
How about using macro?
-
@open 1..2
(Interval{:open,:open}(1,2)
) -
@leftopen 1..2
(Interval{:open,:closed}(1,2)
) -
@rightopen 1..2
(Interval{:closed,:open}(1,2)
)
Existing syntax that could easily be used:
julia> a .. <(b)
julia> a .. ≤(b)
julia> >(a) .. <(b)
Looks quite nice for the right endpoint, the left one could've been better...
From @masonprotter on slack:
julia> using IntervalSets
julia> macro range_str(s)
for (reg, f) ∈ [r"^\[.*\)$" => Interval{:closed, :open},
r"^\(.*\)$" => Interval{:open, :open},
r"^\(.*\]$" => Interval{:open, :closed},
r"^\[.*\]$" => Interval{:closed, :closed}]
m = match(reg, s)
if !isnothing(m)
args = Meta.parse(s[nextind(s, 1):prevind(s, lastindex(s))])
return :($f($(esc(args))...))
end
end
error("unrecognized expresson $s")
end;
julia> let a = 2
range"[1,a)"
end
1 .. 2 (closed-open)
https://julialang.slack.com/archives/C680MM7D4/p1701897935053029?thread_ts=1701897085.625229&cid=C680MM7D4
I think range"[1,2]"
should be interval"[1,2]"
(or iv"[1,2]"
for short) because the returned value is not an AbstractRange
, but using string macro is a great idea.