-
-
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
When are steps of size zero allowed in Ranges? #15218
Comments
I would like to argue that steps of size zero should always be disallowed (and would require methods specialized to numeric-like types to check for this). I have definitely shot myself in the foot many times constructing steps of size zero in the past when home rolling my own ranges in lower level languages. For the applications I am familiar with there is always a tight coupling between the length of a range and the displacement between the two endpoints. Sometimes it makes sense to have a range with one element, but usually these have to be special cased. EDIT: spelling |
I'm actually in favor of allowing zero steps everywhere for the nice arithmetic closure properties that allows. We let people do julia> (1:10) - (0:9)
ERROR: ArgumentError: step cannot be zero
in steprange_last(::Int64, ::Int64, ::Int64) at ./range.jl:30
[inlined code] from ./range.jl:20
in -(::UnitRange{Int64}, ::UnitRange{Int64}) at ./operators.jl:413
in eval(::Module, ::Any) at ./boot.jl:260
julia> (1:1:10) - (0:1:9)
ERROR: ArgumentError: step cannot be zero
in steprange_last(::Int64, ::Int64, ::Int64) at ./range.jl:30
[inlined code] from ./range.jl:20
in -(::StepRange{Int64,Int64}, ::StepRange{Int64,Int64}) at ./operators.jl:413
in eval(::Module, ::Any) at ./boot.jl:260
julia> (1.0:10) - (0.0:9)
10-element FloatRange{Float64}:
1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 That's kind of annoying and harmful to generic programming. There's also the potential in the future that broadcasting could be simply and elegantly implemented by slicing arrays with zero-step ranges. |
What about ranges with almost zero steps? They seem a bit odd.
|
Subtracting two ranges makes sense; of course, in this case, one cannot calculate the length by dividing by the step size. Thus the internal representation needs to change to allow this -- we need |
The case for integer ranges and floating-point ranges is different since floating-point ranges have to handle rounding. Having said this, defining a floating-point range via |
I hadn't thought about doing arithmetic with ranges, but it seems like a good reason to allow steps of size zero. There is a question though of the exceptional case of (1:10) - (0:9) Would this return a |
Any thoughts on this? @timholy, does the new range work you did happen to allow this generally? |
I don't think we're going to take away the current ability to have zero-step float ranges, and if we're going to change this in any direction, it would be to allow zero-step ranges for more range types, not fewer, which makes changing this a non-breaking change. Other issues that came up during discussion:
|
Sorry I hadn't even noticed the earlier discussion. As usual, you've thought more broadly and discovered a reason that argues in favor of something I would have naively said we should disallow. I don't think I put any effort into thinking about zero-step ranges, so if we allow them someone should go through the code and audit it. Addressing some of the specific questions:
|
Oh, one more thing: I should point out that allowing zero-step ranges to be created and having a syntax for them is completely independent. While |
At the moment some
Range
constructors disallow steps of size zero:In other cases it seems to be allowed:
Are the last two examples to be considered bugs or are there some cases in which steps of size zero are considered valid? Whichever the case, there seems to be a need to document the correct behavior both for devs and users.
The text was updated successfully, but these errors were encountered: