Dribbler
Dribbler

Reputation: 4681

ClosedRange and array subscripting in Swift 3

I'm converting my code to Swift 3 and have just 3 buildtime errors left, 2 of which have to do with my lack of understanding how ranges now work. For example, I have:

func shuffle( _ tenseArray: [ Tense ], ...

    var indices = [ Int ]()
    for tense in tenseArray {
        if let aRange = tenseRange[ tense ] { 
            indices.append( aRange )
        }
    }

Where Tense is an enum that looks something like:

 enum Tense: String {
    case IndicativePresent = "Indicative Present"
    case IndicativePreterite = "Indicative Preterite"
    case IndicativeImperfect = "Indicative Imperfect"
    ...

And tenseRange is defined as:

var tenseRange: [ Tense : ClosedRange<Int> ] = [:] // maps Tense enums to ranges of tense indices

and is populated like this:

tenseRange[ Tense.IndicativePresent ] = ( 11 ... 16 )
tenseRange[ Tense.IndicativePreterite ] = ( 17 ... 22 )
tenseRange[ Tense.IndicativeImperfect ] = ( 23 ... 28 )
...

For the line in func shuffle

indices.append( aRange )

I'm getting the error Cannot subscript a value of type '[Int]' with an index of type 'CountableRange'. I really would like to convert those ranges into ints for use in indices of an array as I was able to do previously in Swift, but I can't seem to figure out how. Any ideas?

Thanks in advance!

Upvotes: 2

Views: 1482

Answers (1)

OOPer
OOPer

Reputation: 47896

You declare your indices as an Array of Int, so you cannot use append(_:) for ClosedRange<Int>.

So, I assume you want to append all values in the ClosedRange to indices.

In such cases, you may need to use append(contentsOf:), not append(_:).

Array

...

func append(Element)

Adds a new element at the end of the array.

...

func append(contentsOf: C)

Adds the elements of a collection to the end of the array.

func append(contentsOf: S)

Adds the elements of a sequence to the end of the array.

Unfortunately, in Swift 3, CountableRange<T> is not a Collection nor a Sequence.

But Swift 3 introduced an new Range family types, CountableClosedRange<T> and CountableRange<T>, which are both Collection. And the result type of closed range operator ... can be a CountableClosedRange<T> when placed in a specific context.

        indices.append(contentsOf: aRange.lowerBound...aRange.upperBound)

Or else, you can declare your tenseRange's value as CountableClosedRange<Int>.

var tenseRange: [ Tense : CountableClosedRange<Int> ] = [:]

Upvotes: 2

Related Questions