`compact` and `compactValues`

In the review thread SE-0218 — Introduce compactMapValues to Dictionary there was a discussion about compact and compactMap. I posted a comment earlier this morning demonstrating how these could be implemented using existing language features with the Unwrappable protocol discussed in Introducing `Unwrappable`, a biased unwrapping protocol.

A protocol like that should be debated on its own merit of course, but it's worth pointing out that it would enable algorithms like these to be implemented today in a way that would work over types other than Optional (such as Result).

protocol Unwrappable {
    associatedtype Wrapped
    func unwrap() -> Wrapped?
extension Optional: Unwrappable {
    func unwrap() -> Wrapped? {
        return self
extension Array where Element: Unwrappable {
    func compact() -> [Element.Wrapped] {
        return compactMap { $0.unwrap() }
extension Dictionary where Value: Unwrappable {
    func comactValues() -> [Key: Value.Wrapped] {
        let result = lazy.compactMap { keyValue -> (Key, Value.Wrapped)? in
            guard let value = keyValue.value.unwrap() else {
                return nil
            return (keyValue.key, value)
        return Dictionary<Key, Value.Wrapped>(uniqueKeysWithValues: result)
let array: [Int?] = [42, nil, 42]
let compactArray = array.compact()
let dictionary: [Int: String?] = [42: "42", 43: nil, 44: "44"]
let compactDictionary = dictionary.comactValues()

The review thread is not the appropriate place to continue the discussion of these methods so let's move the conversation here.

1 Like

In the review thread @xwu commented:

I replied: wouldn't _Unwrappable: Unwrappable be a viable workaround for that issue while allowing other types to conform to Unwrappable?

Setting all else aside, I think it would be extremely strange to have a public method on Optional called unwrap that doesn't actually unwrap the optional.


It would be, sure, but the Unwrappable protocol in the link is orthogonal to the topic of working around the lack of parametric extensions. For that, you need a protocol to which only Optional conforms: this is possible with or without the proposal you link to, it's still necessary with or without it, and _Unwrappable as you name it would work around the problem here (lack of parametric extensions) whether or not it refines Unwrappable. Therefore, I think discussion about what you're linking to should be separate from the discussion about compactValues and whether to wait for parametric extensions or work around them--which is in turn distinct from compactMapValues.

I just adopted the syntax used in that thread. I would expect a very healthy round of bike shedding on the exact names were a proposal for this to make it to review.

1 Like

This makes sense to me for the most part. That said, the thread linked above is relevant to the degree that people want a compact family of methods that work with types other than Optional. I am not advocating for that, just trying to establish a framework for discussion. I would like to see the pros and cons of each approach discussed.

Sure, it can be very valuable to compare approaches. I just wanted to clarify for all participants that indeed Unwrappable as proposed in that link is not equivalent to the _Unwrappable workaround for parametric extensions and cannot be used as such.