Unwrapping and value binding patterns in the condition of ternary expressions

I've often written code like the following where I only want a variable unwrapped for a simple ternary expression.

subscript(key: String) -> Widget? {
    get {
        return self.wrappers[key]?.widget
    }
    
    set {
        let wrapped: Wrapper<Widget>?
        if let value = newValue {
            wrapped = Wrapper(value)
        } else {
            wrapped = nil
        }
        
        self.wrappers[key] = wrapped
    }
}

The getter looks great. The setter is a bunch of lines of incantation to do something simple. If I weren't against explicit unwrapping, I could have done this:

self.wrappers[key] = newValue == nil ? nil : Wrapper(newValue!)

Map is also available. I would argue it's not exactly intuitive, could make for ugly lines, and it doesn't work on other pattern matches.

self.wrappers[key] = newValue.map { Wrapper($0) }

So getting to the point: I would prefer something a little more concise and consistent with other conditional branches. What I would like to see is a way to unwrap inline for the duration of the true case or bind enum case values for the duration of the true case.

self.wrappers[key] = (let value = newValue) ? Wrapper(value) : nil

This could support case pattern matches too.

self.wrappers[key] = (case let .some(value) = newValue) ? Wrapper(value) : nil

let intVal = (case let .integer(value)) ? value : 0

let isLlama = (case let .animal(type, _) ? type == .llama : false

I'll be the first to say I'm not thrilled by the syntax, but at least it'd be consistent. Despite looking like an expression, if this were implemented it should probably not be able to be used elsewhere.

Anyone else run into this a lot? Have thoughts or better ideas?

2 Likes

If you really don't want to use ! or map then why not just pattern match it?

    set {
        switch(newValue) {
        case let value?: self.wrappers[key] = Wrapper(value)
        case _: self.wrappers[key] = nil
        }
    }

The switch version is about as good as the version in my post. There's duplicative assign statements in the code you have there.

IMO, it's awfully unwieldy to create a switch/if/guard construct every time a developer would like to extract a value from an enum case to use for a single line.

The lack of ternary usage just kind of sticks out, since Swift encourages conciseness and functional-inspired programming.

1 Like
Terms of Service

Privacy Policy

Cookie Policy