[swift-users] inout generic struct parameter error
David Sweeris
davesweeris at mac.com
Sun Jan 1 15:20:18 CST 2017
> On Jan 1, 2017, at 10:48, Georgios Moschovitis via swift-users <swift-users at swift.org> wrote:
>
> While getting my feet wet with Swift, I am still surprised with type-system ‘quirks’ here and there.
>
> I tried to implement a simple array of weak references:
>
> public struct WeakArrayIterator<T: AnyObject>: IteratorProtocol {
> var array: [Weak<T>]
> var index = 0
>
> init(_ array: [Weak<T>]) {
> self.array = array
> }
>
> mutating public func next() -> T? {
> while index < array.count && array[index].value == nil {
> // Remove weak references invalidated by ARC.
> array.remove(at: index)
> }
>
> if index < array.count {
> let value = array[index].value
> index += 1
> return value
> } else {
> return nil
> }
> }
> }
>
> public struct WeakArray<T: AnyObject>: Sequence {
> var weakRefs: [Weak<T>]
>
> init() {
> weakRefs = []
> }
>
> public var count: Int {
> return weakRefs.count
> }
>
> public subscript(index: Int) -> T? {
> get {
> return weakRefs[index].value
> }
>
> set(value) {
> weakRefs[index] = Weak(value!)
> }
> }
>
> mutating public func append(_ value: T) {
> weakRefs.append(Weak(value))
> }
>
> @discardableResult
> mutating func remove(at index: Int) -> T? {
> return weakRefs.remove(at: index).value
> }
>
> public func makeIterator() -> WeakArrayIterator<T> {
> return WeakArrayIterator(weakRefs)
> }
> }
>
> This kinda works but because we pass a struct at:
>
> return WeakArrayIterator(weakRefs)
>
> the ‘garbage collection’ at:
>
> // Remove weak references invalidated by ARC.
> array.remove(at: index)
>
> doesn’t affect the original array.
>
> I tried changing to this:
>
> public struct WeakArrayIterator<T: AnyObject>: IteratorProtocol {
> ...
> init(_ array: inout [Weak<T>]) {
> self.array = array
> } return WeakArrayIterator(&weakRefs)
> …
>
> public struct WeakArray<T: AnyObject>: Sequence {
> return WeakArrayIterator(&weakRefs)
>
> but I get this strange (to me) error:
>
> Cannot convert value of type ‘[Weak<T>]’ to expected argument type ‘[Weak<_>]’
>
> I even get the fix-it suggestion:
>
> Fix-it Insert “as [Weak<_>]”
>
> which does not even compile!
>
> I would appreciate it if someone could explain me this cryptic error and maybe provide some pointers about how to properly/efficiently implement a WeakArray.
FWIW, whenever I've encountered that message, it's been a sign that I'm either stretching type system a bit past what it can handle, or I've got a subtle error elsewhere in my code...
The passed-in array isn't going to get modified though, because you never change it. At least semantically speaking, arrays in swift are pass-by-value, so when you assign it to your struct's local storage and then later modify the *struct's* variable, only the local copy gets affected. If you want to mutate the passed-in array, you'll have to do it in the function you pass it to.
- Dave Sweeris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20170101/95ba77ae/attachment.html>
More information about the swift-users
mailing list