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

Haravikk swift-evolution at haravikk.com
Thu Jan 21 10:17:06 CST 2016


The tricky thing with ranges at the moment is that they can’t actually represent a full range of an integer type, for example a Range<UInt8> can only represent a range from 0 to 254 (endIndex is 255 but is exclusive). This actually means that a collection type that used a UInt8 for indexes is limited to 255 entries, not 256 as you would expect, which is unfortunate if the collection type allocates storage in powers of two.

I think this means that if ranges were changed to have an inclusive end index then collections would need to be modified to function on the same principal, otherwise we could end up with a range that represents an upper limit that collections cannot, or alternatively we have to artificially limit the supported values for .end, i.e- for a UInt8 .end would be limited to a value of 254, so that .endIndex can be set to 255.

For use with collections I’d love to use inclusive rather than exclusive end indexes for this reason, as while 1 inaccessible element doesn’t seem like much, it still annoys me an unreasonable amount. But would this change the meaning of a range? i.e- 1 ..< 4 isn’t necessarily the same as 1 … 3, it’s only functionally equivalent when dealing with integers since there are no stages in between.

> On 20 Jan 2016, at 23:19, Andrew Bennett via swift-evolution <swift-evolution at swift.org> wrote:
> 
> I agree with Kevin/Jordan, I also expect this to always be true:
> 
>     Range<Int>(start: a, end: b).startIndex == a
>     Range<Int>(start: a, end: b).endIndex == b
> 
> Possibly you could adjust Range to be something like this:
> 
>     struct Range<T: ForwardIndexType> {
>         var start: T, end: T
>     }
> 
> Ensuring that this is true:
>     Range<Int>(start: a, end: b).start == a
>     Range<Int>(start: a, end: b).end == b
> 
> Then startIndex and endIndex are simply for CollectionType conformance.
> 
>     extension Range: CollectionType {
>         var startIndex: T { return start }
>         var endIndex: T { return start < end ? end : start }
>     }
> 
> You can still test the validity of the range:
>     assert(range.start < range.end)
> 
> 
> On Thu, Jan 21, 2016 at 8:23 AM, Jordan Rose via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> Mm. The reason '..<' doesn't have this behavior, though, is because you get the useful property that "collection[collection.startIndex..<collection.endIndex]" contains the same elements as "collection" itself. It's definitely useful to be able to represent an empty slice at a particular position (say, for replacing with another slice). It's a lot rarer to use '...' for slicing.
> 
> Jordan
> 
> 
> > On Jan 20, 2016, at 13:17 , Haravikk <me at haravikk.com <mailto:me at haravikk.com>> wrote:
> >
> > I’m inclined to agree though I’m pretty uncertain all round.
> >
> > To me it seems like the only cases where someone seems likely to end up with an end index lower than their start index is either from input (in which case the value should be tested first), or some kind of logic error, in which case silently failing isn’t going to help resolve that issue (or detect it).
> >
> > Personally I’d much prefer the opposite solution, which would be to have stride throw an error if the range given is invalid; this would still mean both cases are consistent, but without the risk of silent failures ruining your program.
> >
> > - Haravikk
> >
> >> On 20 Jan 2016, at 19:42, Jordan Rose via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> >>
> >> I'm a minor -1; it feels like this is in the same family as nil-messaging in that it can silently treat invalid input as a no-op. I'm not convinced that "upper bound less than the lower bound" is a strong enough signal for "empty" rather than "logic error". But it seems I'm in the minority.
> >>
> >> Jordan
> >>
> >>
> >>> On Jan 19, 2016, at 12:46, Uwe Falck via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> >>>
> >>> 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.
> >>
> >> _______________________________________________
> >> swift-evolution mailing list
> >> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> >> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
> >
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160121/46766acd/attachment.html>


More information about the swift-evolution mailing list