Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get associated value from enumeration without switch/case

Tags:

enums

swift

I've got an enumeration with a few different cases which are different types, e.g.

enum X {
    case AsInt(Int)
    case AsDouble(Double)
}

I can switch on these just fine to get the underlying value back out. However, the switch statement is highly annoying with trying to make me execute some code for the other cases that I simply don't care about. For example, right now I have something like

func AsInt(x: X) -> Int? {
    switch x {
    case AsInt(let num):
        return num;
    default:
        return nil;
    }
}

This works but it's pretty tedious always having to reference this method and having to write a new one for each case of each enumeration. What I'm looking for is how to simply attempt to cast a value of type X to one of the cases, like

var object: X = func();
let value = obj as? Int;
if value {
    // do shit
}

How can I simply check for a case without having to enumerate all of the cases about which I don't care and execute some non-statement for them?

Bonus points for any solution that can declare value as part of the conditional instead of polluting the scope.

like image 664
Puppy Avatar asked Jul 29 '15 11:07

Puppy


People also ask

Can you give useful examples of enum associated values?

For instance, you might describe a weather enum that lists sunny, windy, and rainy as cases, but has an associated value for cloudy so that you can store the cloud coverage. Or you might describe types of houses, with the number of bedrooms being an associated integer.

What is associated value in enum?

In Swift enum, we learned how to define a data type that has a fixed set of related values. However, sometimes we may want to attach additional information to enum values. These additional information attached to enum values are called associated values.

What is the associated value?

Associated values are set when you create a new constant or variable based on one of the enumeration's cases, and can be different each time you do so.

Can enum have stored property?

Although we have said that it can not has stored properties, it can(and in most cases should) has rawValue: meaning of the case in current enum's context. I'm going to demonstrate some cases of usage enums as data model by adding functionality gradually.


2 Answers

There are actually multiple ways to do it.

Let's do it by extending your enum with a computed property:

enum X {
    case asInt(Int)
    case asDouble(Double)

    var asInt: Int? {
        // ... see below
    }
}

Solutions with if case

By having let outside:

var asInt: Int? {
    if case let .asInt(value) = self {
        return value
    }
    return nil
}

By having let inside:

var asInt: Int? {
    if case .asInt(let value) = self {
        return value
    }
    return nil
}

Solutions with guard case

By having let outside:

var asInt: Int? {
    guard case let .asInt(value) = self else {
        return nil
    }
    return value
}

By having let inside:

var asInt: Int? {
    guard case .asInt(let value) = self else {
        return nil
    }
    return value
}

The last one is my personal favorite syntax of the four solutions.

like image 194
Cœur Avatar answered Nov 17 '22 02:11

Cœur


As of Swift 2 (Xcode 7) this is possible with if/case and pattern matching:

let x : X = ...
if case let .AsInt(num) = x {
    print(num)
}

The scope of num is restricted to the if-statement.

like image 29
Martin R Avatar answered Nov 17 '22 01:11

Martin R