👔HasMirrors

💾 程式:replitarrow-up-right ⬆️ 需要:Mirror, Logger

// ────────────────────────────────────────────────────────────
// 2022.01.27 * v.1 + log, reflect, mirror
// 2022.01.28 / log, reflect, mirrorChildren: use `Logger`
//            - rename `item` as `HasMirrors`
//            + default conformances: Int, Double
//            + extend [HasMirrors]: `items.log()`
//            + Bool.log(): custom conformance
// ────────────────────────────────────────────────────────────

// ┌──────────────────┐
// │    HasMirrors    │
// └──────────────────┘

public protocol HasMirrors {
    /// `item.log()`
    func log() -> Self              // for chaining
    /// `item.reflect()`
    func reflect() -> Self          // for chaining
    /// `item.mirror()`
    func mirror() -> Self           // for chaining
}

// ⭐ default behaviors
extension HasMirrors {

    /// `item.log()`
    @discardableResult
    public func log() -> Self { 
        Logger.log(String(describing: self), dot: "🍄")
        return self 
    }
    
    /// `item.reflect()`
    @discardableResult
    public func reflect() -> Self { 
        Logger.log(String(reflecting: self), dot: "🍄")
        return self 
    }
    
    // mirrorChildren (object tree)
    @discardableResult
    func mirrorChildren<T>(of subject: T) -> Self {
    
        let title = "\(String(describing: subject))"
        Logger.box(title)
        
        
        // ⭐ mirror children
        let children = Mirror(reflecting: subject).children
        if children.count == 0 { print("  // no children") }
        
        children.forEach { child in
            let label = "\(child.label ?? "_")"
            let value = " \(child.value)"
            let valueType = " (\(type(of: child.value)))"
            Logger.log(label + ":" + value + valueType, dot: "🔸")
        }
        
        Logger.line(title.count + 10)
        return self
    }
    
    /// `item.mirror()`
    @discardableResult
    public func mirror() -> Self {
        return mirrorChildren(of: self)
    }
}

// ┌──────────────────────────────┐
// │    [HasMirrors] extension    │
// └──────────────────────────────┘

extension Array where Element == HasMirrors {
    /// `items.log()`
    @discardableResult
    public func log() -> Array { 
        self.forEach { _ = $0.log() }  // _: silence compiler warning.
        return self 
    }
}

// ┌────────────────────────────┐
// │    default conformances    │
// └────────────────────────────┘

extension String: HasMirrors {}
extension Int   : HasMirrors {}
extension Double: HasMirrors {}

extension Bool  : HasMirrors {
    public func log() -> Bool {
        Logger.log(self ? "" : "")
        return self
    }
}

History

  1. (2022.01.27) - original post

Last updated