Expressing a range of values is an extremely common concept when programming, which is why I *love* that Swift includes a robust collection of types to represent ranges as part of its standard library. No more ad-hoc utility types for ranges with slightly different semantics scattered around your codebase, or having to choose between a number of third-party implementations (*cough* Java).

Swift ranges are actually pretty powerful, so here are five tips that'll let you work with them more effectively.

`Range`

vs `ClosedRange`

There are actually *two* types of complete range in the standard library: `Range`

, and `ClosedRange`

.

They're very similar, but the semantics of the ranges that they represent differ; whereas the range represented by a `Range`

*does not* include its `upperBound`

, that represented by a `ClosedRange`

*does*.

So when should you use either? One common use of `Range`

is iterating over a number of integer indexes, which may be 0-indexed. In this case, the index for the count of the elements itself is *not* valid, so we don't want to include it.

```
// `..<` gives us a `Range`.
for i in 0..<userCount {
// Fetch the user at `i`.
}
```

On the contrary, I typically find `ClosedRange`

useful when working with `Date`

s (or any form of timestamp). If you want to express an *inclusive* time range, then `ClosedRange`

is the way to go.

```
// `...` gives us a `ClosedRange`.
for day in today...nextSunday {
// Process the day. `nextSunday` will be included!
}
```

Even if you're just using the `lowerBound`

and `upperBound`

properties internally (in which case both ranges perform identically), ensuring that you expose the correct range type as part of your API makes the range semantics of your operation clear.

# Partial Ranges

Did I imply that there are only two types of ranges? I lied - there are actually *5*.

What are those funny partial ranges? They're exactly what you'd imagine - open ranges where you specify one bound, but not the other.

`PartialRangeFrom`

is an open range where you just specify the lower bound. *All* possible values greater than or equal to that are semantically included in the range. As such, it has no `upperBound`

property.

```
// `...` gives us a `PartialRangeFrom`.
let todayOrLater = today...
```

`PartialRangeUpTo`

is effectively a `Range`

where you only specify the upper bound (so there's no `lowerBound`

). *All* possible values less than that bound are semantically included in the range.

```
// `..<` gives us a `PartialRangeUpTo`.
let beforeToday = ..<today
```

`PartialRangeThrough`

is its companion (similar to the `Range`

/`ClosedRange`

split). Again, you only specify the upper bound, but *all* possible values less that *or equal to* that bound are semantically included in that range.

```
// `...` gives us a `PartialRangeThrough`.
let beforeEndOfWeek = ...sunday
```

(I promise there are no more range types to cover).

**So!** In summary,

`Range`

:`lowerBound..<upperBound`

(lowerBound <= x < upperBound)`ClosedRange`

:`lowerBound...upperBound`

(lowerBound <= x <= upperBound)`PartialRangeFrom`

:`lowerBound...`

(lowerBound <= x)`PartialRangeUpTo`

:`..<upperBound`

(x < upperBound)`PartialRangeThrough`

:`...upperBound`

(x <= upperBound)

# Checking for Containment

All of the ranges covered so far have a `.contains(_:)`

method to verify whether an element is included.

```
let myRange = 1..<5
myRange.contains(2) // true
myRange.contains(5) // false
```

However, there's also a handy operator that you can use for the same purpose. (Saying that, I *always* get the order of the range and the value to check wrong).

```
let myRange = 1..<5
myRange ~= 2 // true
myRange ~= 5 // false
```

# Ranges as `Collection`

s

Both `Range`

and `ClosedRange`

are fully-fledged `Collection`

s themselves, whenever the bound is *stridable* using integer increments, anyway (a fancy way of saying, the jump between elements is well defined). This means you can do any of the normal `Collection`

-type interactions with them, such as dropping elements, or taking a count.

```
let range = 1..<5
range.dropLast(2) // 1..<3
range.count // 4
```

Furthermore, you can easily use ranges to initialize another collection of their included elements. The common case is building an array of incrementing integers.

```
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
let values = Array(1..<10)
```

`PartialRangeFrom`

is an infinite `Sequence`

, starting at the lower bound. This means you can iterate over one, however clearly you need to bail out at some point.

```
for x in 3... {
// Need to stop at some point!
break
}
```

`PartialRangeUpTo`

and `PartialRangeThrough`

have no such `Sequence`

/`Collection`

conformance. If you think about it, what's the first element?

~

Thanks for reading! I'd love to hear your feedback; feel free to contact me directly.