Julia: step(::StepRangeLen{T}) converts step to T

Created on 18 Nov 2019  ·  5Comments  ·  Source: JuliaLang/julia

https://github.com/JuliaLang/julia/blob/05a80e1e82ac976bd3323f10e1139d86b3954cbe/base/range.jl#L503

StepRangeLen does not ask that S be convertable to T, but requires it in step.

It seems like this was done intentionally for Floats but doesn't account for cases where the step can't (or shouldn't) be converted to the type of the start. This would come up more often for AbstractTime, but AbstractTime has the exact combination of traits to prevent it from being implicitly created by range.

julia> StepRangeLen(DateTime(2018,1,1), Hour(1), 2)
2018-01-01T00:00:00:0001-01-01T01:00:00:2018-01-01T01:00:00

That's not a correct value for the step.

In the case of https://github.com/invenia/Intervals.jl/issues/78, it's not even possible to convert the step to the type of the start, so errors are thrown.

Not sure what the right resolution here is but I don't think we should leave it as is.

bug

All 5 comments

I believe this is so that twice precision steps return a float instead of the twice precision that is only used internally. Perhaps there should be a separate

step(r::StepRangeLen{T,TwicePrecision{T},TwicePrecision{T}}) where {T} = T(r.step) 

This is weird for ranges of characters, too:

julia> r = 'a':'z'   # StepRange{Char,Int64}
'a':1:'z'

julia> sr = range(first(r), step = step(r), length=length(r))  # StepRangeLen{Char,Char,Int64}
'a':'\x01':'z'

julia> sr.step
1

julia> step(sr)
'\x01': ASCII/Unicode U+0001 (category Cc: Other, control)

I have a whole laundry list of things that could be done to improve performance of ranges that I've begun implementing over in https://github.com/Tokazama/StaticRanges.jl but I'm once again at war with IT to stop blocking Julia. So if someone else makes a PR I'd be happy to review it.

Yes, this is definitely a bug.

This fix for this created an issue with Unitful units.

This code:

1/step(range(1s, stop=10s, length=10))

gives me this error

MethodError: no method matching /(::Int64, ::Base.TwicePrecision{Quantity{Float64,𝐓,Unitful.FreeUnits{(s,),𝐓,nothing}}})

In a nightly build.

Was this page helpful?
0 / 5 - 0 ratings