Rodrigo Ruiz
Rodrigo Ruiz

Reputation: 4355

Access enum associated value as optional

How can I access an enum value for a specific case without having to implement an enum function for each case?

I'm thinking something like this:

enum Result<S, F> {

    case success(S)
    case failure(F)

}

let resultSuccess = Result<Int, String>.success(1)
let resultFailure = Result<Int, String>.failure("Error")

let error: String? = case let .failure(error) = resultFailure

Something like this would also be acceptable:

let error: String? = (case let .failure(error) = resultFailure) ? error : ""

Obviously this doesn't even compile, but that's the gist of what I want.

Is that possible?

EDIT: explaining why my question is not the same as Extract associated value of enum case into a tuple

It's very simple, that answer access the values inside the if statement, rather than as an Optional like in my question. To specify a little more, imagine I have to extract values from multiple enums, and maybe enums inside enums, for that I'd need nested if's, or guard's, but with guard I wouldn't be able to continue the flow, since it forces a return.

Upvotes: 1

Views: 2040

Answers (3)

思齐省身躬行
思齐省身躬行

Reputation: 181

Add two computed properties for success case and failure case respectively.

enum Result<S, F> {
  case success(S)
  case failure(F)

  var successValue: S? {
    switch self {
    case .success(let value):
      return value
    case .failure:
      return nil
    }
  }

  var failureValue: F? {
    switch self {
    case .failure(let value):
      return value
    case .success:
      return nil
    }
  }
}


let resultSuccess = Result<Int, String>.success(1)
let resultFailure = Result<Int, String>.failure("Error")

if let error = resultFailure.failureValue {
  // do something
  print(error)
}

Upvotes: 1

user887210
user887210

Reputation:

This technique from the question "Accessing an Enumeration association value in Swift" will do it:

enum Result<S, F> {
  case success(S)
  case failure(F)
}

let resultFailure = Result<Int, String>.failure("Error")

var error: String?

if case let Result.failure(value) = resultFailure {
  error = value
}

print(error) // Optional("Error")

This will also work in place of the "if case let =" construct:

switch resultFailure {
case let Result.failure(value): error = value
default                       : error = nil
}

Here you go, 1 line and uses let:

let error: String? = { if case let .failure(value) = resultFailure { return value }; return nil }()

Upvotes: 0

Vojta Rujbr
Vojta Rujbr

Reputation: 335

I'm afraid this is the most you can get:

    let error: String?
    if case .failure(let e) = resultFailure {error = e}

Upvotes: 0

Related Questions