I want to create an array of random numbers (Int, Int32)
I tried the following:
map(1...1000) { arc4random() }
but it returns the following error:
error: type 'ClosedInterval<T>' does not conform to protocol 'SequenceType'
What I'm doing wrong?
For some reason, a minor tweak to my first attempts seems to work just fine
map(1...1000) { $0 - $0 + arc4random() }
The problem, now, is that I don't understand why this tweaked approached works and why the initial approach does not...
Any ideas?
Swift is willing to infer types, but it can only deal with so much ambiguity before it gives up.
In the case of map(1...100) { arc4random() }
, there’s too much uncertainty about what the types are. Specifically, the integer literals 1 and 100. They could be Int
, Int8
, UInt32
… Sometimes Swift will default to Int
but if there’s more ambiguity in the statement it can get thrown off-balance and refuse to.
In this case, in the same statement it’s trying to figure out what the type of { arc4random() }
is. It ought to be able to infer that the return type is UInt32
because that’s what arc4random
returns. But what’s the input type? You aren’t using it in the expression, so it doesn’t matter, but Swift has to make it something, and it doesn’t know what.
The reason writing { $0 - $0 + arc4random() }
fixes it is that helps determine what the type of $0
is – it has to be a UInt32
because that’s the only thing that you can add to the output of arc4random
. So that makes the type of the closure UInt32 -> UInt32
. Which means the type of the 1
and the 100
must also be UInt32
. Which means 1...10
must be a Range
Finally, the reason you’re getting a complaint about ClosedInterval
not conforming to SequenceType
is because there are two possible return types for the ...
operator – Range
and ClosedInterval
. You want a Range
but Swift doesn’t know that – it can’t make Range
or ClosedInterval
work. Swift compiler errors have a tendency to list one of the many possible options that won’t work, usually not the one you were trying for, which can be a bit confusing.
The better way to fix this without resorting to the $0 - $0
trick is probably something like this:
let a = map(1...100) { _ in arc4random() }
The _
indicates you don’t care about the input to the closure. Supplying an input argument (even an anonymous one) seems to be enough to let Swift relax a little bit and default to Int
for the two integer literals.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With