Ian Hsiao
Ian Hsiao

Reputation: 305

Swift: Cannot convert value of type 'Range<Int>' to specified type 'Int'

I was trying to implement a small iteration which returns the square of some ranges.

Which should be the equivalence of this Python script

for i in range(n):
    print(i*i)

In Swift I tried

first attempt

let numbers = [1..<10]

for i in numbers{
    print(i*i)
}

and

second attmpt

let numbers = [1..<10]

for i in numbers{
    var j: Int = i
    print(j*j)
}

but then the compiler says Cannot convert value of type 'Range<Int>' to specified type 'Int'

I understand from my python experience this is due to different types in Swift. Thus my questions are

  1. How can I fix this? (i.e. implement the same thing i did in python)
  2. What are the problems with my first and second attempts?
  3. Why are there so many types of <Int> in Swift?

Thanks in advance!

Upvotes: 1

Views: 2251

Answers (1)

Sweeper
Sweeper

Reputation: 271355

Your code doesn't compile because you have used [] around the range, which creates an array. [1..<10] is an array of ranges. The for loop is then iterating over that array, which has only one element - the range 1..<10.

This is why i is of type Range<Int>. It is the range, not the numbers in the range.

Just remove the [] and both of your code would work. You can iterate over ranges directly (in fact, anything that conforms to the Sequence protocol), not just arrays. You can even write the range inline with the loop:

for i in 0..<10 {
    print(i * i)
}

Why are there so many types of <Int> in Swift?

You are looking at this the wrong way, the word Range and ClosedRange in the types Range<Int> and ClosedRange<Int> are not words that modify Int, as if they are different "flavours" of Int. It's the opposite - Range<Bound> and ClosedRange<Bound> are generic types, and Range<Int> can be a considered the specific "type" of Range that has Int as its bounds. You can also have Range<Float> or Range<UInt8> for example.

Upvotes: 3

Related Questions