[swift-evolution] Let range operators always return empty ranges if the upper bound is smaller than the lower bound.

Denis Nikitenko d.nikitenko at icloud.com
Wed Jan 20 08:10:59 CST 2016


Another hearty +1 from me as well.  I’ve run into this recently and used the stride-based work-round.  However, using 

for i in startIndex.stride(through: endIndex, by: 1){
...
} 

instead of 

for i in startIndex…endIndex{
…
}

solely so that the body of the loop never executes if startIndex > endIndex seems unnecessary - especially since 

for i in startIndex…<endIndex+1{
…
}

works perfectly fine.  It would make sense to make `…` and `..<` consistent with each other and return an empty range in this case - which would also be consistent with the overall behaviour of stride().

Denis


> On Jan 20, 2016, at 3:55 AM, Thorsten Seitz via swift-evolution <swift-evolution at swift.org> wrote:
> 
> +1
> 
> -Thorsten 
> 
> Am 20.01.2016 um 02:32 schrieb Howard Lovatt via swift-evolution <swift-evolution at swift.org>:
> 
>> +1 from me. I have been caught by this. In the degenerate case I didn't want the loop to be processed, but instead I got a runtime error. I solved the problem by changing to a C style for loop, but with the removal of C style for loops this will be more of a problem. 
>> 
>> This could be solved with a library function as already suggested, however having `...`, `..<`, `...?`, and `..<?` seems excessive. Therefore my suggestion is to make `...` & `..<` behave as proposed (i.e. return empty ranges when limits mean nothing enclosed by range).
>> 
>> On Wednesday, 20 January 2016, Félix Cloutier <swift-evolution at swift.org> wrote:
>> I don't have a strong opinion on this, but maybe there could be a ..<?/...? operator for ranges that may or may not be well-formed? This solution can be implemented "at home" too.
>> 
>> I'd love to see where and how developers use ranges. It may be more helpful than it looks like. For instance, if you use a range to get an array slice, would your rather have an empty slice if your range underflows instead of the current error behavior?
>> 
>> Félix
>> 
>>> Le 19 janv. 2016 à 15:46:00, Uwe Falck via swift-evolution <swift-evolution at swift.org> a écrit :
>>> 
>>> I’m looking for feedback on this request if its worth to start an evolution proposal.
>>> 
>>> 
>>> Let range operators always return empty ranges if the upper bound is smaller than the lower bound.
>>> 
>>> ####
>>> 
>>> Introduction
>>> 
>>> ####
>>> 
>>> Consider two loops. The first loop iterator will return an empty range and will not be executed. The second loop throws an error. I would like to see the range iterator always returning an empty range if end index < start index. 
>>> 
>>> for i in 3..<3 
>>> { print(i) }
>>> 
>>> for i in 3…2
>>> { print(i) }
>>> 
>>> 
>>> ####
>>> 
>>> Motivation
>>> 
>>> ####
>>> 
>>> The two expressions above are mathematically equivalent and I would like them to return the same result for consistency.
>>> 
>>> Furthermore, and more important: if C-style for loops are gone with Swift 3.0, programmers may translate 
>>> 
>>> func fibonacci(n: Int) -> Int {                            // works for n>=0
>>> 	var memo = [0,1]
>>> 	for var i = 2; i <= n; i++ {
>>> 		memo.append(memo[i-1] + memo[i-2])
>>> 	}
>>> 	return memo[n]
>>> }
>>> 
>>> probably into
>>> 
>>> func fibonacci(n: Int) -> Int {				// works only for n>=2!
>>> 	var memo = [0,1]
>>> 	for i in 2...n {
>>> 		memo.append(memo[i-1] + memo[i-2])
>>> 	}
>>> 	return memo[n]
>>> }
>>> 
>>> This example is from Stackoverflow[1] with two suggested solutions to prevent the runtime error for 0 and 1
>>> 
>>> let startIndex = 2
>>> let endIndex = n
>>> for i in startIndex.stride(through: endIndex, by: 1) {
>>> 	memo.append(memo[i-1] + memo[i-2])
>>> }
>>> 
>>> …and another one uses the empty range generate by  ..<
>>> 
>>> for i in 2 ..< max(2, n+1) {
>>> 	memo.append(memo[i-1] + memo[i-2])
>>> }
>>> 
>>> Clearly the not-working-solution looks most logical. All other control flow elements, like while, will just not execute if their condition is not met on loop entry.
>>> 
>>> 
>>> #####
>>> 
>>> Proposed solution
>>> 
>>> #####
>>> 
>>> Let both range iterators return emtpy ranges, if end index < start index, and not only for a..<b with a==b.
>>> 
>>> #####
>>> 
>>> Impact on existing code
>>> 
>>> #####
>>> 
>>> None.
>>> 
>>> ####
>>> 
>>> Alternatives considered
>>> 
>>> ####
>>> 
>>> If range operators will allow downward variants this idea becomes pointless.
>>> 
>>> ####
>>> 
>>> Open questions
>>> 
>>> ####
>>> 
>>> None.
>>> 
>>> 
>>> [1] http://stackoverflow.com/questions/34323227/a-concise-way-to-not-execute-a-loop-now-that-c-style-for-loops-are-going-to-be-r?lq=1
>>> 
>>> 
>>> Thanks,
>>> 
>>> 
>>> --
>>> 
>>> Uwe
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> 
>> 
>> -- 
>>   -- Howard.
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list