# Unwrapping and value binding patterns in the condition of ternary expressions

**URL:** <https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803>\
**Category:** Pitches\
**Created:** [October 9, 2018, 7:01am UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803 "2018-10-09T07:01:53Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![mkasiano](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@mkasiano](https://forums.swift.org/u/mkasiano)\
**Post date:** [October 9, 2018, 7:01am UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/1 "2018-10-09T07:01:53Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![Nobody1707](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nobody1707/32/2169_2.png) [@Nobody1707](https://forums.swift.org/u/Nobody1707)\
**Post date:** [October 9, 2018, 5:44pm UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/2 "2018-10-09T17:44:56Z")

</div>

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

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

```

---

<div class="post-metadata">

**Author:** ![mkasiano](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@mkasiano](https://forums.swift.org/u/mkasiano)\
**Post date:** [October 9, 2018, 5:52pm UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/3 "2018-10-09T17:52:45Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![jeremyabannister](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jeremyabannister/32/10143_2.png) [@jeremyabannister](https://forums.swift.org/u/jeremyabannister)\
**Post date:** [September 3, 2019, 5:50am UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/4 "2019-09-03T05:50:05Z")

</div>

I just wrote about something similar - my suggested syntax is less robust but more ergonomic:

> [@New Convenient Behavior for Ternary Operator](https://forums.swift.org/t/new-convenient-behavior-for-ternary-operator/28467):
>
> I dislike when I have to do this: value != nil ? self.useValue(value!) : self.doSomethingElse() I dislike it because the type system is powerful and helpful, and using ! means turning off the type system and just winging it. However, doing this within the type system takes up a completely unnecessary number of lines and just feels like too much boilerplate: if let value = value { self.useValue(value) } else { self.doSomethingElse() } For this use case, I think it would more elegant a…

---

<div class="post-metadata">

**Author:** ![DeFrenZ](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/defrenz/32/827_2.png) [@DeFrenZ](https://forums.swift.org/u/DeFrenZ)\
**Post date:** [September 3, 2019, 10:34am UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/5 "2019-09-03T10:34:52Z")

</div>

What about

```swift
set {
  self.wrappers[key] = newValue.map(Wrapper.init)
}

```

?

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [September 3, 2019, 5:40pm UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/6 "2019-09-03T17:40:50Z")

</div>

> [@mkasiano](#):
>
> ```swift
> 
> let wrapped: Wrapper<Widget>?
> if let value = newValue {
> wrapped = Wrapper(value)
> } else {
> wrapped = nil
> }
>         
> self.wrappers[key] = wrapped
> 
> ```

FWIW, in the case I would favor:

```swift
guard let newValue = newValue else {
    wrappers[key] = nil
    return
}
wrappers[key] = Wrapper(newValue)

```

I may be a controversial opinion, but personally I think adding features to ternary expressions should generally be discouraged. IMO it's pretty much a legacy feature from C-based languages that would not have been added otherwise. It's far from clear, confusing for new users, and easily abused. (That said, I use it somewhat liberally 😇)

As for not wanting to use map, I agree it feels unintuitive and a bit confusing. I almost never use it even though It's semantically similar to Kotlin's `thing.let{}` which I use all the time. I think this is due to it's naming being identical to `Collection.map`, while functionally having a very different use.

Regarding the issues with pattern matching, IMO that's an issue with the poor ergonomics around it and `associatedValue` outside of Switches, which will hopefully be improved soon, e.g. [Extract Payload for enum cases having associated value - #105 by trs](https://forums.swift.org/t/extract-payload-for-enum-cases-having-associated-value/27606/105).

---

<div class="post-metadata">

**Author:** ![mattpolzin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mattpolzin/32/6041_2.png) [@mattpolzin](https://forums.swift.org/u/mattpolzin)\
**Post date:** [September 3, 2019, 6:09pm UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/7 "2019-09-03T18:09:45Z")

</div>

> [@GetSwifty](#):
>
> As for not wanting to use map, I agree it feels unintuitive and a bit confusing. I almost never use it even though It's semantically similar to Kotlin's `thing.let{}` which I use all the time. I think this is due to it's naming being identical to `Collection.map` , while functionally having a very different use.

`Optional.map` and `Collection.map` functionally have the same use, given the right conceptual framing. In both cases, you are unwrapping a value, applying a function to it, and wrapping it back up again. “Functor” is not the first word you learn in an intro programming course, and in fact you can use all sorts of monadic types without caring about the topic conceptually. Still, if you read up on Functors (or Monads) you’ll start to see the connections between `Optional.map`, `Collection.map`, `Result.map`, etc. in a new light.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [September 3, 2019, 6:48pm UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/8 "2019-09-03T18:48:29Z")

</div>

> [@mattpolzin](#):
>
> `Optional.map` and `Collection.map` functionally have the same use, given the right conceptual framing.

I would say they're _semantically_ or _conceptually_ similar, but the practical/functional use is different.

Even the documentation is different:

> `Optional.map`:  
> /// Evaluates the given closure when this `Optional` instance is not `nil`,  
> /// passing the unwrapped value as a parameter.

> `Array.map`:  
> /// Returns an array containing the results of mapping the given closure  
> /// over the sequence's elements.

`Optional.map` is focused on _unwrapping_, not _transforming_. IME that's also the primary way/reason it's used.

In addition it only applies to `Optional`. You can't do `5.map{"\($0)"}`, so there's no related use-case for using `.map` to transform single values. So the use cases are: Collection-Transforms and Unwrap-Optional-with-a-transform-if-you-want.

Yes at a theoretical/"Functional Programming" level the same thing is being accomplished, but the _use_ of each of them is meaningfully different enough that one concept doesn't easily map (😁) to the other.

Not to mention the confusing situation where you have an `Optional<Collection>`:

```swift
let foo: [String]? = ["bar"]
foo.map {} // here you have a [String] passed in
foo?.map {} // here you have each Element passed in

```

---

<div class="post-metadata">

**Author:** ![mattpolzin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mattpolzin/32/6041_2.png) [@mattpolzin](https://forums.swift.org/u/mattpolzin)\
**Post date:** [September 3, 2019, 7:15pm UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/9 "2019-09-03T19:15:36Z")

</div>

> [@GetSwifty](#):
>
> You can't do `5.map{"\($0)"}` , so there's no related use-case for using `.map` to transform single values

Yeah, and from the “monadic” conceptual model this makes sense because `5` is not of a monadic type. `Int` does not wrap anything.

I’ll grant you that Swift is not really trying to give us monads and the documentation totally avoids the topic for good reason. I’m not suggesting that if you don’t think of these types as Functors then you are thinking about them incorrectly — what I _am_ saying is that when I personally started to see these types as monadic I started to feel much more empowered to work with `map/flatMap` and I consider that to be a very positive thing for my code writing and reading in general.

---

<div class="post-metadata">

**Author:** ![mkasiano](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@mkasiano](https://forums.swift.org/u/mkasiano)\
**Post date:** [September 4, 2019, 8:47pm UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/10 "2019-09-04T20:47:36Z")

</div>

Wow, my thread was revived! From almost a year ago! I'm glad there's some interest in the topic.

Much of this discussion is focusing on `Optional`. It's good that we have `map` (though it's neither discoverable _nor_ readable), but I would like to see enums generally be more useable.

Enums with associated types are a pretty neat feature of Swift. However, they require more lines and more unique syntax than alternatives - the primary alternative being a closed class hierarchy. Enums save in declaration verbosity at the expense of usage verbosity - and that's the _exact opposite_ of what a developer wants! The only advantages I see are 1) compile time checking (switch statement warnings/errors) 2) specific performance consideration (stack allocation).

If a developer ends up making enough extension methods on the enum to make it reasonably useable, it may as well have been a class to start with, as the class and class hierarchy can at least be extended as the application grows.

Working under the assumption that enums are a type that should be favored when possible, the syntax should **not** be punitive. `if case` is pretty unintuitive, IMO, which leaves us with `switch` and manually written `map`-like extensions.

For illustration, let's say we have a `DatabaseValue` type and want to extract a string if the stored type is a string:

```
enum DatabaseValue {
    case string(_: String)
    case integer(_: Int)
    // ...
}

func printStringValue(_ dbValue: DatabaseValue) {
    let result: String
    if case let .string(strValue) = dbValue {
        result = strValue
    } else {
        result = ""
    }
    print("the string is \(result)")
}

```

But if DatabaseValue were a root class:

```
class DatabaseValue {
}

class StringDatabaseValue: DatabaseValue {
    public let stringValue: String
   //...
}

func printStringValue(_ dbValue: DatabaseValue) {
    let result = (dbValue as? StringDatabaseValue)?.stringValue ?? ""
    print("the string is \(result)")
}

```

The latter usage is denser, but more readable: the reader knows that `result` is being calculated here and can skim past it. It is only when the reader wants to know _how_ `result` is being derived that the readability becomes debatable. **Since extracting a value from an enum is such an insignificant task when compared to other code, it doesn't deserve vertical space.**

Another alternative is `Any`, if it applies:

```
func printStringValue(_ dbValue: Any) {
    let result = (dbValue as? String) ?? ""
    print("the string is \(result)")
}

```

Why would we want to encourage `Any` over enum types?

The current syntax for enum usage seems to hold the opinion "if you are using an enum, you will want to handle all of its cases everywhere, so a switch statement is just fine". In my experience, this is an unrealistic expectation.

To bring things back around, it is my opinion that **unwrapping and using a value from an enum, whether it's Optional or another, should _always_ be possible within a single statement.** Once you need block statements or helper extensions to extract a value, the wrapper type's usage semantics are just adding rote signal noise.

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [September 4, 2019, 9:12pm UTC](https://forums.swift.org/t/unwrapping-and-value-binding-patterns-in-the-condition-of-ternary-expressions/16803/11 "2019-09-04T21:12:53Z")

</div>

There's been effort recently to improve `enum` ergonomics in [DiscriminatedUnion Protocol](https://forums.swift.org/t/discriminatedunion-protocol/28094) and [Extract Payload for enum cases having associated value](https://forums.swift.org/t/extract-payload-for-enum-cases-having-associated-value/27606)
