Home > Software engineering >  Is there a way in Swift to get an associated value without using a switch statement?
Is there a way in Swift to get an associated value without using a switch statement?

Time:08-08

When I have a situation where I already know enum case statement I want to get the associated value of, is there a cleaner way than using a switch statement to pluck out the associated value?

To have to come up with a switch statement, provide multiple cases, or a default case just to extract the associated value is gaudy.

enum CircularReasoning {
    case justPi(pi: Double)
    case pizzaPie(howMany: Int)
}

var piInTheSky : Double 

let whatLogic = CircularReasoning(pi: 3.1415926)

switch whatLogic {
    case .justPi(let pi):
        piInTheSky = pi!
    default:
        break
}

I have looked through existing s.o. q&a on this and couldn't find anything that really addresses this scenario clearly.

CodePudding user response:

You can use if case .<enum_case>(let value) as in TylerP's example, or if case let .<enum_case>(value):

enum Foo {
    case anInt(Int)
    case aFloat(Float)
}

let aFoo: Foo = .anInt(9)

// Example of `if case .<enum_case)(let value)` syntax:
if case .anInt(let aValue) = aFoo {
    print("aFoo = anInt(\(aValue))")

// Example of `if case let .enum_case(value)` syntax:
} else if case let .aFloat(aValue) = aFoo {
    print("aFoo = aFloat(\(aValue))")
}

Both work. I'm not sure why the language includes both variants.

If you only care about one enum type, then either if syntax makes sense to me. If you are dealing with more than one possible enum value then the switch version seems cleaner.

CodePudding user response:

Here's an adaptation of @DuncanC's excellent upvoted and accepted answer, as applied to a fictitious version of my real-world use case.

It illustrates a possible way to use his answer to reduce the space required to extract associated values, especially if one has a lot of one-off cases...

Note: Not implying this is appropriate or professional swift styling; it's clearly idiosyncratic, yet compact. (I usually don't compress things into one liners like this, unless they get really repetitive/redundant & produce lot of pointless vertical bloat).

enum RealmKey { case realmOfRealms, anyOldRealm, someOtherRealm }
.
.
.
enum SymbolToken {
    case realm       (key: RealmKey?)
    case space       (key: SpaceKey?)
    case area        (key: AreaKey?)
    case region      (key: RegionKey?)
    case preserve    (key: PeserveKey?)
    case openParen
    case closeParen
    case logicalAnd
    case logicalOr
    case logicalNot
    
    var realmKey    : RealmKey?    { if case .realm    (let key) = self { return key } else { return nil } }
    var spaceKey    : SpaceKey?    { if case .space    (let key) = self { return key } else { return nil } }
    var areaKey     : AreaKey?     { if case .area     (let key) = self { return key } else { return nil } }
    var regionKey   : RegionKey?   { if case .region   (let key) = self { return key } else { return nil } }
    var preserveKey : PreserveKey? { if case .preserve (let key) = self { return key } else { return nil } }
}

let realm = SymbolToken.realm(.realmOfRealms)
let realmKey = realm.realmKey
  • Related