Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shortest code to create an array of random numbers in swift?

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?

like image 470
marco alves Avatar asked Jan 09 '23 03:01

marco alves


1 Answers

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.

like image 146
Airspeed Velocity Avatar answered Jan 31 '23 09:01

Airspeed Velocity