EnumKit

1.0.0

EnumKit is a library that gives you the ability to simply access an enum associated value, without having to use pattern matching. It also offers many utilities available to other swift types, like updatability of an associated value and transformations.
gringoireDM/EnumKit

What's New

2019-08-18T16:54:37Z

Introduced CaseAccessible protocol to easy match enum cases, access and transform associated values, and conditionally execute a block of code when a enum case match a specific enum pattern.

This release also add an extension for Sequence to easily filter and transform enum cases.

Build Status codecov Swift Package Manager swfit5.0

EnumKit

EnumKit is a library that gives you the ability to simply access an enum associated value, without having to use pattern matching. It also offers many utilities available to other swift types, like updatability of an associated value and transformations.

EnumKit comes with an extension of Sequence to extend functions like compactMap, flatMap, filter to Sequences of enums cases.

All you need to do to get these features is to declare your enum conformant to the marker protocol CaseAccessible.

enum MyEnum: CaseAccessible { ... }

Index

Access an associated value

There are two ways to access an associated value of an enum case

By type

The first is by specifying which is your return type and using the associatedValue() function.

let value: String? = someCase.associatedValue()
// or with subscript
let value = someCase[expecting: String.self] // String?

This will return a string if the associated value of this enum instance is actually a string, regardless of which is the actual case. This is particularly useful for those enums that have similar cases, like

enum MyError: CaseAccessible, Error {
    case notFound(String)
    case noConnection(String)
    case failedWithMessage(String)
}

By case

The second way to access an enum associated value is to optionally extract it when the instance is matching a specific case, using the associatedValue(matching:) function:

let myError: MyError
let errorMessage = myError.associatedValue(matching: MyError.noConnection) // String?
// or with subscript
let errorMessage = myError[case: MyError.noConnection] // String?

Matching cases

EnumKit provides utilities functions for case matching.

// is matching

let isConnectionIssue = myError.matches(case: MyError.noConnection)
//or with ~= operator
let isConnectionIssue = myError ~= MyError.noConnection

// is not matching

let isNotConnectionIssue = myError.isNotMatching(case: MyError.noConnection)
// or with !~= operator
let isNotConnectionIssue = myError !~= MyError.noConnection

Updatathing an enum value

Currently to update an associated value of an enum value is very verbose.

Let's take in consideration a simple example:

enum State: CaseAccessible {
    case count(Int)
    case error
}

This code change the value of an enum instance when this represent a count case:

func changeCount(_ state: inout State, to newValue: Int) {
    guard case .count = state else { return }
    state = State.count(newValue)
}

func incrementCount(_ state: inout State, by increment: Int) {
    guard case let .count(value) = state else { return }
    state = State.count(value + increment)
}

while with EnumKit this becomes

func changeCount(_ state: inout State, to newValue: Int) -> State {
    state[case: State.count] = newValue
}

func incrementCount(_ state: inout State, by increment: Int) {
    state[case: State.count, default: 0] += increment
}

Transform associated values

Similarly to Optional, EnumKit offers map and flatMap functions to transform associated values, when the enum is CaseAccessible

struct Person {
    var name: String
    var lastName: String
}

enum MyEnum: CaseAccessible {
    case myString(String)
    case myInt(Int)
    case myPerson(Person)
}

let aCase: MyEnum
...

let stringValue = aCase.map(case: MyEnum.myInt) { "\($0)" } // String?
let name = aCase.map(case: MyEnum.myPerson) { $0.name } // String?
let maybeInt = aCase.flatMap(case: MyEnum.myString) { Int($0) } // Int?

These operators work exactly the same as for Optional. While Optional map and flatMap functions will invoke the transformation just when Optional case is some, the equivalent functions will invoke the transformation just if they match the specific case specified in the case parameter.

Description

  • Swift Tools 5.0.0
View More Packages from this Author

Dependencies

  • None
Last updated: Wed Mar 20 2024 09:11:19 GMT-0900 (Hawaii-Aleutian Daylight Time)