# Open-ended range?

**URL:** https://discourse.julialang.org/t/open-ended-range/102287
**Category:** General Usage
**Created:** [July 31, 2023, 4:36am UTC](https://discourse.julialang.org/t/open-ended-range/102287 "2023-07-31T04:36:14Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)
#### Post date: [July 31, 2023, 4:36am UTC](https://discourse.julialang.org/t/open-ended-range/102287/1 "2023-07-31T04:36:14Z")

</div>

I often need a range that doesn’t include the last point:

```julia
function func(x1, x2, del)
for x in x1:del:x2
# but I want the loop only for x != x2

```

Depending on the values of `x1`, `x2`, and `del`, the loop sometimes includes `x == x2`.

Is there already a library function or a user-defined type to handle this case? Needless to say, you can always terminate the loop by

```julia
for x in x1:del:x2
   (x == x2) && break
   . . .

```

Also, if you go fancy, you can define your own type with your own iterator to achieve this.

But, I just want to know what I’m missing, before writing inelegant code like the above example or going the fancy way of wring a custom type.

---

<div class="post-metadata">

### Author: ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)
#### Post date: [July 31, 2023, 6:13am UTC](https://discourse.julialang.org/t/open-ended-range/102287/2 "2023-07-31T06:13:47Z")

</div>

Maybe

```julia
for x in x1:del:x2-del
    ...

```

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [July 31, 2023, 6:20am UTC](https://discourse.julialang.org/t/open-ended-range/102287/3 "2023-07-31T06:20:30Z")

</div>

Why not just `(x1:del:x2)[1:end-1]`?

```julia
julia> x1 = 3; del = 2; x2 = 19;

julia> x1:del:x2
3:2:19

julia> (x1:del:x2)[1:end-1]
3:2:17

```

---

<div class="post-metadata">

### Author: ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)
#### Post date: [July 31, 2023, 6:30am UTC](https://discourse.julialang.org/t/open-ended-range/102287/4 "2023-07-31T06:30:17Z")

</div>

```julia
for x in x1:del:x2-del

```

In the initial post, I should have written that that’s _not_ a solution:

```julia
function func(x1, del, x2)
  display(collect(x1:del:x2))
  display(collect(x1:del:(x2-del)))
end
x1 = 0.0
x2 = 2.5
delx = 1.0
func(x1, del, x2)

```

In this case, `x1:del:x2` is what I want, because all the values satisfy `x < x2`.

Unless you know the values of `x1`, `x2`, and `del` beforehand, it’s impossible to determine whether `x2` or `x2 - del` is the right end of the UnitRange I want.

---

<div class="post-metadata">

### Author: ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)
#### Post date: [July 31, 2023, 6:44am UTC](https://discourse.julialang.org/t/open-ended-range/102287/5 "2023-07-31T06:44:38Z")

</div>

> Why not just `(x1:del:x2)[1:end-1]` ?

Because you can’t tell whether `(x1:del:x2)[1:end]` or `(x1:del:x2)[1:end-1]` is the correct answer:

```julia
0.0:1.0:2.5 # -> [0.0, 1.0, 2.0] < 2.5 . . . I want this!
0.0:1.0:2.0 # -> [0.0, 1.0, 2.0] . . . I don't want this because 2.0 == x2

```

Only when you know the values of `x1`, `del`, and `x2` can you tell whether `x1:del:x2` is the right one or not.

I’m not making this up. My real need is to generate a range of `DataTime` that doesn’t include the end point:

```julia
using Dates
t1 = DateTime(1988,1,1)
t2 = DateTime(2023,12,31)
delt = Dates.Day(3)
t1:delt:t2 # Does this sequence include t2 ?

```

You can’t answer the question unless you actually calculate the range `t2 - t1` in the units of days and divide it by 3.

It’s inelegant that you have to do such a calculation each time you handle different values that constitute the range.

---

<div class="post-metadata">

### Author: ![albheim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/albheim/32/34660_2.png) [@albheim](https://discourse.julialang.org/u/albheim)
#### Post date: [July 31, 2023, 6:54am UTC](https://discourse.julialang.org/t/open-ended-range/102287/6 "2023-07-31T06:54:55Z")

</div>

Ahh, felt like it was too simple. Maybe you can just remove a machine epsilon for the type? Feels hacky but works for your example.

```julia
julia> x = 0
0

julia> y1 = 2.5
2.5

julia> y2 = 2.0
2.0

julia> del = 1.0
1.0

julia> x:del:y1-eps(y1)
0.0:1.0:2.0

julia> x:del:y2-eps(y2)
0.0:1.0:1.0

```

---

<div class="post-metadata">

### Author: ![longemen3000](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/longemen3000/32/7298_2.png) [@longemen3000](https://discourse.julialang.org/u/longemen3000)
#### Post date: [July 31, 2023, 7:12am UTC](https://discourse.julialang.org/t/open-ended-range/102287/7 "2023-07-31T07:12:31Z")

</div>

this package seems like the solution for the problem: [GitHub - jw3126/RangeHelpers.jl: Make ranges not bugs](https://github.com/jw3126/RangeHelpers.jl), but it does not support Date ranges. (PR incoming)

---

<div class="post-metadata">

### Author: ![longemen3000](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/longemen3000/32/7298_2.png) [@longemen3000](https://discourse.julialang.org/u/longemen3000)
#### Post date: [July 31, 2023, 7:28am UTC](https://discourse.julialang.org/t/open-ended-range/102287/8 "2023-07-31T07:28:23Z")

</div>

in this particular case:

```julia
using RangeHelpers, Dates
t1 = DateTime(1988,1,1)
t2 = DateTime(2023,12,31)
delt = Dates.Day(3)
r = RangeHelpers.range(start = t1, step = delt, stop = strictbelow(t2))

```

that gives:

```julia
julia> RangeHelpers.range(start = t1, stop = strictbelow(t2), step = delt)
DateTime("1988-01-01T00:00:00"):Day(3):DateTime("2023-12-29T00:00:00")

julia> RangeHelpers.range(start = 0.0, stop = strictbelow(2.0),step = 1.0)
0.0:1.0:1.0

julia> RangeHelpers.range(start = 0.0, stop = strictbelow(2.5),step = 1.0)
0.0:1.0:2.0

```

---

<div class="post-metadata">

### Author: ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)
#### Post date: [July 31, 2023, 7:49am UTC](https://discourse.julialang.org/t/open-ended-range/102287/9 "2023-07-31T07:49:39Z")

</div>

It sure sounds like that there should be a package for that out there somewhere…

How about this?

```julia
Iterators.takewhile(<(x2), x1:del:x2)

```

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [July 31, 2023, 7:55am UTC](https://discourse.julialang.org/t/open-ended-range/102287/10 "2023-07-31T07:55:37Z")

</div>

> [@ryofurue](#):
>
> `x1:del:x2`

Just for the sake of clearer communication, the above is not a `UnitRange`, but a `StepRangeLen`. In fact, even

```julia
julia> (1.0:3.0) isa UnitRange
false

```

It’s better to just call it a ‘range’, maybe you should rename the thread to “Open-ended range?”

Maybe you can try something like (for float inputs only)

```julia
openrange(start, stop, step) = range(start, prevfloat(stop); step)

```

(I also like the `takewhile`-solution of @HanD, though it seems to be slower, probably due to repeated comparisons).

---

<div class="post-metadata">

### Author: ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)
#### Post date: [July 31, 2023, 8:17am UTC](https://discourse.julialang.org/t/open-ended-range/102287/11 "2023-07-31T08:17:34Z")

</div>

> Just for the sake of clearer communication, the above is not a `UnitRange`, but a `StepRangeLen`.  
> [. . .]  
> It’s better to just call it a ‘range’, maybe you should rename the thread to “Open-ended range?”

Thank you for your kind correction! Yes, I’ve edited my initial post. [Edit: I’ve also edited the other one which also included the wrong terminology.]

---

<div class="post-metadata">

### Author: ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)
#### Post date: [July 31, 2023, 10:39am UTC](https://discourse.julialang.org/t/open-ended-range/102287/12 "2023-07-31T10:39:27Z")

</div>

```julia
julia> function openrigthrange(sta, ste, sto)
           len=Int((sto-sta) ÷ ste)+1
           sto1= sta+(len-1)*ste
           len-=(sto1 >=sto)
           range(start=sta,length=len,step=ste)
       end
openrigthrange (generic function with 1 method)

julia> openrigthrange(0.,1.1,3.0)
0.0:1.1:2.2

julia> openrigthrange(0.,1.1,3.3)
0.0:1.1:2.2

```

---

<div class="post-metadata">

### Author: ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)
#### Post date: [July 31, 2023, 3:28pm UTC](https://discourse.julialang.org/t/open-ended-range/102287/13 "2023-07-31T15:28:09Z")

</div>

I may have misunderstood you . . . Your example doesn’t compile. Did you mean that in the future the `RangeHelpers` package will work as you describe?

Here is the code

> [@longemen3000](#):
>
> ```julia
> using RangeHelpers, Dates
> t1 = DateTime(1988,1,1)
> t2 = DateTime(2023,12,31)
> delt = Dates.Day(3)
> r = RangeHelpers.range(start = t1, step = delt, stop = strictbelow(t2))
> 
> ```

which doesn’t compile. See the error listing at the end of this message. The `range` function seems to be trying to compare an `Int` with a `Day`. I’m using `RangeHelpers v0.1.9`.

```julia
ERROR: LoadError: MethodError: no method matching isless(::Int64, ::Day)

Closest candidates are:
  isless(::Union{Month, Quarter, Year}, ::Union{Day, Hour, Microsecond, Millisecond, Minute, Nanosecond, Second, Week})
   @ Dates ~/.julia/juliaup/julia-1.9.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.9/Dates/src/periods.jl:439
  isless(::P, ::P) where P<:Period
   @ Dates ~/.julia/juliaup/julia-1.9.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.9/Dates/src/periods.jl:71
  isless(::Period, ::Period)
   @ Dates ~/.julia/juliaup/julia-1.9.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.9/Dates/src/periods.jl:97
  ...

Stacktrace:
 [1] <(x::Int64, y::Day)
   @ Base ./operators.jl:343
 [2] <=(x::Int64, y::Day)
   @ Base ./operators.jl:392
 [3] >=(x::Day, y::Int64)
   @ Base ./operators.jl:416
 [4] start_step_stop(start::DateTime, step::Day, stop::RangeHelpers.Approach{DateTime})
   @ RangeHelpers ~/.julia/packages/RangeHelpers/crKui/src/RangeHelpers.jl:246
 [5] range1(start::DateTime, step::Day, stop::RangeHelpers.Approach{DateTime}, length::Nothing)
   @ RangeHelpers ~/.julia/packages/RangeHelpers/crKui/src/RangeHelpers.jl:231
 [6] range(start::DateTime; stop::RangeHelpers.Approach{DateTime}, length::Nothing, step::Day)
   @ RangeHelpers ~/.julia/packages/RangeHelpers/crKui/src/RangeHelpers.jl:141
 [7] range0(start::DateTime, step::Day, stop::RangeHelpers.Approach{DateTime}, length::Nothing)
   @ RangeHelpers ~/.julia/packages/RangeHelpers/crKui/src/RangeHelpers.jl:154
 [8] range(; start::DateTime, stop::RangeHelpers.Approach{DateTime}, length::Nothing, step::Day)
   @ RangeHelpers ~/.julia/packages/RangeHelpers/crKui/src/RangeHelpers.jl:137
 [9] top-level scope
   @ ~/Dropbox/tmp/try-openrange.jl:5
in expression starting at /Users/furue/Dropbox/tmp/try-openrange.jl:5

```

---

<div class="post-metadata">

### Author: ![longemen3000](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/longemen3000/32/7298_2.png) [@longemen3000](https://discourse.julialang.org/u/longemen3000)
#### Post date: [July 31, 2023, 4:52pm UTC](https://discourse.julialang.org/t/open-ended-range/102287/14 "2023-07-31T16:52:31Z")

</div>

> [@ryofurue](#):
>
> I may have misunderstood you . . . Your example doesn’t compile. Did you mean that in the future the `RangeHelpers` package will work as you describe?
> 
> Here is the code

yes, the example does not compile, because of a bug in the library, that i’m fixing at the moment ([0 -\> `zero(step)` by longemen3000 · Pull Request #3 · jw3126/RangeHelpers.jl · GitHub](https://github.com/jw3126/RangeHelpers.jl/pull/3))
