NullHypothesis - 6 months ago 156

iOS Question

I was using this extension method to generate a random number:

`func Rand(_ range: Range<UInt32>) -> Int {`

return Int(range.lowerBound + arc4random_uniform(range.upperBound - range.lowerBound + 1))

}

I liked it b/c it was no nonsense, you just called it like this:

`let test = Rand(1...5) //generates a random number between 1 and 5`

I honestly don't know why things need to be so complicated in Swift but I digress..

So i'm receiving an error now in Swift3

`No '...' candidates produce the expected contextual result type 'Range<UInt32>'`

Would anyone know what this means or how I could get my awesome Rand function working again? I guess x...y no longer creates Ranges or x..y must be explicitly defined as UInt32? Any advice for me to make things a tad easier?

Thanks so much, appreciate your time!

Answer

In Swift 3 there are four Range structures:

`"x" ..< "y"`

⇒`Range<T>`

`"x" ... "y"`

⇒`ClosedRange<T>`

`1 ..< 5`

⇒`CountableRange<T>`

`1 ... 5`

⇒`CountableClosedRange<T>`

(The operators `..<`

and `...`

are overloaded so that if the elements are stridable (random-access iterators e.g. numbers and pointers), a Countable Range will be returned. But these operators can still return plain Ranges to satisfy the type checker.)

Since Range and ClosedRange are different structures, you cannot implicitly convert a them with each other, and thus the error.

If you want Rand to accept a ClosedRange as well as Range, you must overload it:

```
// accepts Rand(0 ..< 5)
func Rand(_ range: Range<UInt32>) -> Int {
return Int(range.lowerBound + arc4random_uniform(range.upperBound - range.lowerBound))
}
// accepts Rand(1 ... 5)
func Rand(_ range: ClosedRange<UInt32>) -> Int {
return Int(range.lowerBound + arc4random_uniform(range.upperBound + 1 - range.lowerBound))
}
```