# CaseReflectable

{% tabs %}
{% tab title="👔 CaseReflectable" %}
💾 程式：[paiza.io](https://paiza.io/projects/BgeXldbalSZcvt3C_5qcQg)    ⬆️ 需要： [mirror](https://lochiwei.gitbook.io/ios/swift/debugging/mirror "mention"), [hasmirrors](https://lochiwei.gitbook.io/ios/swift/debugging/hasmirrors "mention")

```swift
// --------------------------
//     ⭐ CaseReflectable
// --------------------------

// designed for enums only (use it on other types not recommended)
public protocol CaseReflectable: Loggable {
    /// log enum case (default implementation provided)
    func logEnumCase() -> Self
}

// ⭐ default behavior.
extension CaseReflectable {
    
    /// ⭐ case name
    public var caseName: String {
        let mirror = Mirror(reflecting: self)
        // enum cases:
        // - normal case: no children
        // - case with associated values: one child (with label)
        guard let label = mirror.children.first?.label else {
            return "\(self)"    // normal case
        }
        // ase with associated values
        return label
    }
    
    /// ⭐ associated values
    public var associatedValues: Any? {
        // if no children, a normal case, no associated values.
        guard let firstChild = Mirror(reflecting: self).children.first else {
            return nil
        }
        // return associated values
        return firstChild.value
    }
    
    /// ⭐ log enum case
    @discardableResult
    public func logEnumCase() -> Self {
        if let values = self.associatedValues {
            print("case: .\(caseName), values: \(values), type: \(type(of: values))")
        } else {
            print("case: .\(caseName) (no associated values)")
        }
        return self
    }
}

// -----------------------------
//     ⭐ custom operator ~=
// -----------------------------

/// match enum cases with associated values, while disregarding the values themselves.
/// usage: `Enum.enumCase ~= instance`
public func ~= <Enum: CaseReflectable, AssociatedValue>(
    // an enum case (with associated values)
    enumCase: (AssociatedValue) -> Enum,    // enum case as function
    // an instance of Enum
    instance: Enum
) -> Bool 
{
    // if no associated values, `instance` can't be of `enumCase`
    guard let values = instance.associatedValues else { return false }
    // if associated values not of the same type, return false
    guard values is AssociatedValue else { return false }
    // create an instance from `enumCase` (as function)
    let case2 = enumCase(values as! AssociatedValue)
    // if same case name, return true
    return case2.caseName == instance.caseName
}
```

{% endtab %}

{% tab title="💈範例" %}
💾 程式：[paiza.io](https://paiza.io/projects/BgeXldbalSZcvt3C_5qcQg)    ⬆️ 需要： 👔 CaseReflectable

```swift
// enum with associated values
enum Rank {
    case number(Int)
    case jack, queen, king
    case ace(suit: Character)
    case range(min: Int, max: Int)
}

// ⭐ enum cases
let cases: [Rank] = [ 
    .jack, 
    // jack
    // Main.Rank.jack
    // no children
    .number(7), 
    // number(7)
    // Main.Rank.number(7)
    // • number: 7 (Int)
    .ace(suit: "♠️"),
    // ace(suit: "♠️")
    // Main.Rank.ace(suit: "♠️")
    // • ace: (suit: "♠️") ((suit: Character))]
    .range(min: 3, max: 8),
    // range(min: 3, max: 8)
    // Main.Rank.range(min: 3, max: 8)
    // • range: (min: 3, max: 8) ((min: Int, max: Int))
]

// 👔 Loggable
cases.forEach { $0.log().reflect().mirror() }

// 👔 CaseReflectable (case name, associated values)
cases.forEach { $0.logEnumCase() }
// case: .jack (no associated values)
// case: .number, values: 7, type: Int
// case: .ace, values: (suit: "♠️"), type: (suit: Character)
// case: .range, values: (min: 3, max: 8), type: (min: Int, max: Int)
```

{% endtab %}

{% tab title="📗 參考" %}

* [x] SwiftLee ⟩ [Reflection in Swift: How Mirror works](https://www.avanderlee.com/swift/reflection-how-mirror-works/)  ⭐️ (inspiration)
* [ ] iJoshSmith ⟩ [Reflectable enums in Swift 3](https://ijoshsmith.com/2017/04/08/reflectable-enums-in-swift-3/)
  {% endtab %}

{% tab title="🗣 討論" %}

* [how to use `if case` statement as boolean in swift](https://stackoverflow.com/questions/67189140/how-to-use-if-case-statement-as-boolean-in-swift) (inspiration from [Jessy](https://stackoverflow.com/a/67204360/5409815))
* [How to filter array of enums with associated values?](https://stackoverflow.com/questions/30973826/how-to-create-a-predicate-to-filter-array-of-enums-with-associated-values-in-swi/70827654#70827654)
  {% endtab %}

{% tab title="👥 相關" %}

* [enum-case-pattern](https://lochiwei.gitbook.io/ios/swift/pattern-matching/enum-case-pattern "mention") - pattern matching
* [operator](https://lochiwei.gitbook.io/ios/swift/pattern-matching/operator "mention") - pattern matching
* [mirror](https://lochiwei.gitbook.io/ios/swift/debugging/mirror "mention") - required struct.
  {% endtab %}

{% tab title="⬆️ 需要" %}

* [mirror](https://lochiwei.gitbook.io/ios/swift/debugging/mirror "mention")
* [hasmirrors](https://lochiwei.gitbook.io/ios/swift/debugging/hasmirrors "mention")
  {% endtab %}

{% tab title="⬇️ 應用" %}

* [filter-cases](https://lochiwei.gitbook.io/ios/swift/type/category/basic/enum/filter-cases "mention")
  {% endtab %}
  {% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lochiwei.gitbook.io/ios/swift/debugging/casereflectable.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
