๐CaseReflectable
๐พ ็จๅผ๏ผpaiza.io โฌ๏ธ ้่ฆ๏ผ Mirror, HasMirrors
// --------------------------
// โญ 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
}
๐พ ็จๅผ๏ผpaiza.io โฌ๏ธ ้่ฆ๏ผ ๐ CaseReflectable
// 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)
enum case pattern - pattern matching
operator (~=) - pattern matching
Mirror - required struct.
Last updated