Exploring Range Types in Swift

One of the many great things that came with Swift 3 release was the Range API on the Swift Standard Library, and since then, it was only improving. Before it, we only had the NSRange that is part of the Foundation framework.

In today’s article, I’ll try to explain what I learned about the Range, ClosedRange, PartialRangeUpTo, PartialRangeThrough and CountableRange, the differences between all of this types of range and how they can be used.

So … let's start

Range

First, let's talk about range and then we can explore the others.

From Apple Standard Library Documentation Range is …

A half-open interval over a comparable type, from a lower bound up to, but not including, an upper bound.

The range type has a Bound generic type that can be any type that conforms to Comparable protocol. That means you can create ranges with Int, Double, Strings … and even your own custom types since they conform to the Comparable protocol.

ClosedRange

From Apple Standard Library Documentation ClosedRange is …

An interval over a comparable type, from a lower bound up to, and including, an upper bound.

The only difference between the Range and ClosedRange is that the ClosedRange includes the upper bound.

CountableRange

From Apple Standard Library Documentation, CountableRange is …

Since Swift 4.1, just a typealias for Range<Bound> where Bound conforms to Strideable and Bound.Stride conforms to SignedInteger.

As you can see below in the definition of the typealias.

And by taking advantage of conditional conformance, Range conforms to Sequence, Collection, BidirectionalCollection, RandomAccessCollection where where Bound conforms to Strideable and Bound.Stride conforms to SignedInteger, meaning where is a CountableRange.

As you can see the conditional conformance definition in the Standard Library Sources on stdlib/public/core/Range.swift

Code snippet from the std/public/core/Range.swift

So, you can work with the range as a Collection and have access to functions distance, indexes, reverse, map, filter and so on …

The same rules are applied to CountableClosedRange with the difference that is a typealias for ClosedRange<Bound> applying the same conformance to Strideable and Bound.Stride conformance to SignedInteger constraints.

And now the upper bound is now included in the Collection.

As you can see the CountableClosedRange includes 5 in the collection

OBS: The Array transformation was only made so we can see on the playground, the range and closed are already a Collection.

PartialRangeUpTo

Again …

From the Apple Standard Library Documentation, PartialRangeUpTo is …

A partial half-open interval up to, but not including, an upper bound.

Is the same of the Range, but it only have the upper bound.

PartialRangeUpTo creation and usage

PartialRangeThrough

One more time …

From the Apple Standard Library Documentation, is PartialRangeThrough …

A partial half-open interval up to, and including, an upper bound.

Is the same of the ClosedRange, but you only have the upper bound.

PartialRangeThrough creation and usage

PartialRangeFrom

I swear this is the last one …

From the Apple Standard Library Documentation, PartialRangeFrom is …

A partial interval extending upward from a lower bound.

Is the same of the ClosedRange, but you only have the lower bound.

PartialRangeFrom creation and usage

Contains in Range

The protocol RangeExpression, which is one of the protocols that all of these types of ranges conforms to, defines a method called contains that can verify if a value is contained within the range. Also there is the ~= operator that does the same checking.

As you can see it's very simple and very useful. If you are curious and want to see how those types are implemented under the hood, you can look into the Standard Library Sources on stdlib/public/core/Range.swift on the Swift's Repo.

Conclusion

There are a lot more interesting things about Ranges that I didn’t cover here, and the API is still getting better and better in all the new releases of Swift. The intention here was just to show the basics and provide examples to demonstrate how you can use it. I referenced all the links to the Apple Documentation and also a link the Swift Standard Library Range.swift.gyb Source, so you can see it for more details if you are curious.

That’s all for this one, hope you like it :)

If I got something wrong or you got some comment or question, please let me know. I’ll be really happy receiving your feedback, so I can make the next articles better :)

You can find me on twitter at @LucianoPassos11 or on github at LucianoAlmeida.

Thanks for reading :)

Like what you read? Give Luciano Almeida a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.