> On Jan 1, 2017, at 10:48, Georgios Moschovitis via swift-users 
> <swift-users@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
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to