Darren Oakey
Darren Oakey

Reputation: 3654

swift simplifying operations with optional variables

I'm pretty much a beginner to swift. I am doing a lot of calculations with values that are intrinsically possibly not there, and I am constantly running into this pattern:

        var lost : Double? = nil
        if let original = original_value, let current = start_value {
            lost  = original - current
        }
        self.lost = lost

which works, but seems ridiculously more complex than it should be. I know I can go and define a minus between two optional doubles, which I will probably do, but I'm looking for a simplification for the generic case - is there generic way of doing essentially a x?.y operation across multiple variables - particularly I want to avoid having to have a variable which you assign twice. I was hoping you could do something like this:

    self.lost = if let original = original_value, let current = start_value {original-current}

or this:

    self.lost = (let original = original_value, let current = start_value ) ? original - current : nil

but it appears not - but I'm aiming for something like that

Upvotes: 2

Views: 76

Answers (1)

user652038
user652038

Reputation:

The standard library doesn't offer a great tool for it. Here's the best I know of, which I think is actually bad.

lost = original_value.flatMap { original in
  start_value.map { original - $0 }
}

I do it like this in my own code:

lost = Optional(original_value, start_value).map(-)
public extension Optional {
  /// Exchange two optionals for a single optional tuple.
  /// - Returns: `nil` if either optional is `nil`.
  init<Wrapped0, Wrapped1>(_ optional0: Wrapped0?, _ optional1: Wrapped1?)
  where Wrapped == (Wrapped0, Wrapped1) {
    self = .init((optional0, optional1))
  }

  /// Exchange two optionals for a single optional tuple.
  /// - Returns: `nil` if either tuple element is `nil`.
  init<Wrapped0, Wrapped1>(_ optionals: (Wrapped0?, Wrapped1?))
  where Wrapped == (Wrapped0, Wrapped1) {
    switch optionals {
    case let (wrapped0?, wrapped1?):
      self = (wrapped0, wrapped1)
    default:
      self = nil
    }
  }
}

Upvotes: 1

Related Questions