Search code examples
arraysswiftswift-extensions

Array extension, Ambiguous reference to member 'subscript'


I'm trying to write an extension to Array in Xcode's playground. I want to write a function that will modify the array so that it will be filled with 0s when the function is called. The code I'm attempting to use is this:

import Foundation

extension Array {
    mutating func zero() {
        for i in 0..<self.count {
            self[i] = 0 // ERROR - Ambiguous reference to member 'subscript'
        }
    }
}

This code does not run, because of the error at:

self[i] = 0

However, if I try to 'get' a value from self, I have no issues. For example:

import Foundation

extension Array {
    mutating func zero() {
        for i in 0..<self.count {
            print(self[i])
        }
    }
}

has no errors and runs as expected.

So my question is; Why can't I modify the array?

Also, Replacing:

self[i] = 0

with,

self.append(0)

also results in an error. (Cannot invoke 'append' with an argument list of type '(Int)')

So it won't let me modify self at all it seems.


Solution

  • It will work if you do the following:

    extension Array where Element: IntegerLiteralConvertible {
        mutating func zero() {
            for i in 0..<self.count {
                self[i] = 0
            }
        }
    }
    

    You must constrain the type of the elements allowed, because you can't, for example, zero out an array of Strings.

    It's important to remember, when extending something like an Array, that you take into account what types of elements are valid for the method you're adding. If it requires elements of a certain type, you constrain on it and then it will work. That way you can only use your zero() method on Arrays containing ints. You might define a different version for an array of Strings that replaces everything in the array with the string "zero", for example, and that implementation will only be used on the type that you constrain it to as well.