๐HasMirrors
๐พ ็จๅผ๏ผreplit โฌ๏ธ ้่ฆ๏ผ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
    }
}๐พ ็จๅผ๏ผ replit
struct Person: HasMirrors {
    let name: String
    let age : Int
}
func testHasMirrors() {
    let joe = Person(name: "Joe", age: 8)
    joe.log().reflect().mirror()
}Result:
// ๐ Person(name: "Joe", age: 8)
// ๐ main.Person(name: "Joe", age: 8)
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// โ    Person(name: "Joe", age: 8)    โ
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// ๐ธ name: Joe (String)
// ๐ธ age: 8 (Int)
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ- CaseReflectable (protocol) - inherits from Loggable. 
- NonNominalTypeWrapper (struct) - conforms to Loggable. 
History
- (2022.01.27) - original post 
๐พ ็จๅผ๏ผpaiza.io โฌ๏ธ ้่ฆ๏ผMirror
// 2022.01.27 * first version
// -------------------
//     โญ Loggable
// -------------------
public protocol Loggable {
    /// show `String(describing: self)` by default
    func log() -> Self
    /// show `String(reflecting: self)` by default
    func reflect() -> Self
    /// show `Mirror(reflecting: self).children` by default
    func mirror() -> Self
}
// โญ default behaviors
extension Loggable {
    @discardableResult
    public func log() -> Self { print(String(describing: self)) ; return self }
    
    @discardableResult
    public func reflect() -> Self { print(String(reflecting: self)) ; return self }
    
    // mirrorChildren (object tree)
    @discardableResult
    func mirrorChildren<T>(of subject: T) -> Self {
    
        let selfDesc = "    children of \(String(describing: subject))    "
        let line = String(repeating: "-", count: selfDesc.count)
        
        print()
        print(line)
        print("\(selfDesc)")
        print(line)
        
        // โญ mirror children
        let children = Mirror(reflecting: subject).children
        if children.count == 0 { print("  // no children") }
        
        children.forEach { child in
            print("  โข \(child.label ?? "_"): \(child.value) (\(type(of: child.value)))")
        }
        
        print(line)
        print()
        
        return self
    }
    
    @discardableResult
    public func mirror() -> Self {
        mirrorChildren(of: self)
    }
}Last updated
Was this helpful?