Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"ambiguous subscript" when trying to return an array

Tags:

arrays

swift

I'm looking to extract sub-arrays in Swift 4 and running into unexpected difficulties.

The following trivial cases work as expected:

let array1 = ["a", "b", "c","x","y","z"]
array1[2...3]  // returns ["c","x"], as it should

as does the following variation:

let m=2
let n=3
array1[m...n]  // returns ["c","x"], as it should

But if I try to create a function around this, I get an error message ambiguous subscript with base type 'Array<Any>' and index type 'CountableClosedRange<Int>':

func arrayTake(arrayIn: Array<Any>) -> Array<Any> {
    return arrayIn[2...3]
}     // no good

And of course, the following form, which is closer to what I actually want to do, fails with the same error message:

func arrayTake(m: Int, n: Int, arrayIn: Array<Any>) -> Array<Any> {
    return arrayIn[m...n]
}     // no good

I have seen other questions here about ambiguous subscripts but have not been able to translate the answers there into a solution to my problem. Any guidance would be appreciated.

like image 612
Michael Stern Avatar asked Feb 12 '18 04:02

Michael Stern


2 Answers

You are getting such error because you are trying to return an ArraySlice instead of the expected Array<Any>:

Slices Are Views onto Arrays

You may want to convert such slice using a dedicated Array constructor:

func arrayTake(m: Int, n: Int, arrayIn: Array<Any>) -> Array<Any> {
    return Array<Any>(arrayIn[m...n])
}

Moreover, please note that long-term storage of ArraySlice is discouraged, a slice holds a reference to the entire storage of a larger array, not just to the portion it presents, even after the original array’s lifetime ends. Long-term storage of a slice may therefore prolong the lifetime of elements that are no longer otherwise accessible, which can appear to be memory and object leakage.

like image 150
Andrea Mugnaini Avatar answered Sep 29 '22 05:09

Andrea Mugnaini


Problem is Datatype mismatch.

array1[2...3] This statement does not return Array it returns ArraySlice a special DataType (struct) for this kind of array operation.

So you can solve this by two way.

Change return type to ArraySlice

func arrayTake(m: Int, n: Int, arrayIn: Array<Any>) -> ArraySlice<Any> 
{   
    return arrayIn[m...n] 
}

OR

Convert ArraySlice to Array

func arrayTake(m: Int, n: Int, arrayIn: Array<Any>) -> Array<Any> {  
    return Array(arrayIn[m...n])    
}

Both will print same output but keep in mind that they are not same:

let array1 = ["a", "b", "c","x","y","z"]
let result = arrayTake(m: 2, n: 3, arrayIn: array1)

print(result) //["c","x"], as it should

Check this for more detail: https://medium.com/@marcosantadev/arrayslice-in-swift-4e18522ab4e4

like image 39
CRDave Avatar answered Sep 29 '22 05:09

CRDave