๐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