skip to Main Content

I have a following method:

private func returnNilIfEmpty<T: Collection>(_ collection: T?) -> T? {
    guard let collection = collection else { return nil }
    return collection.isEmpty ? nil : collection
}

I’d like to extend the Collection API to use a computed variable to extract the non-empty value like this:

extension Collection {
    var nonEmptyValue: Collection? {
        returnNilIfEmpty(self)
    }
}

However, I’m getting the error:

Protocol ‘Collection’ can only be used as a generic constraint because
it has Self or associated type requirements

Which is clear, as the outer Collection can be any collection (e.g. an [Int]) while the collection inside the returnNilIfEmpty can be e.g. a String.

The question is how can I enforce the rule that the Collection returned via nonEmptyValue and the one returned via returnNilIfEmpty of the same type, so that I can get rid of this compiler error?

2

Answers


  1. Chosen as BEST ANSWER

    Using Self solves the issue, since it points to the concrete type of the collection:

    import Foundation
    
    extension Collection {
        var nonEmptyValue: Self? {
            returnNilIfEmpty(self)
        }
    }
    
    func returnNilIfEmpty<T: Collection>(_ collection: T?) -> T? {
        guard let collection = collection else { return nil } // nil -> return nil
        return collection.isEmpty ? nil : collection // return nil if empty
    }
    
    

    Simplified even further:

    import Foundation
    
    extension Collection {
        ///
        var nonEmptyValue: Self? {
            self.isEmpty ? nil : self
        }
    }
    

  2. It is appropriate to use Self here:

    extension Collection {
        var nonEmptyValue: Self? {
            returnNilIfEmpty(self)
        }
    }
    

    If e.g. you did Set([1,2,3]).nonEmptyValue, you’d expect to get a Set<Int>? rather than a general Collection? (you don’t even know what kind of elements this type contains or anything like that!), wouldn’t you?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search