Printing intermediate results within method chains

To see the intermediate results in a chain sequence (method chaining, fluent pattern) without breaking the chain I created the following extension:

extension Loggable {
    @discardableResult func log() -> Self {
        log(nil)
    }
    @discardableResult func log(_ title: String?) -> Self {
        if let title = title {
            print(title, " ", self)
        } else {
            print(self)
        }
        return self
    }
}

// MARK: also this
extension Int: Loggable {}
extension String: Loggable {}
extension Foo: Loggable {}
// and so on

so now I can write:

let x = foo
    .bar(...)
    .map { ... }
    .log("intermediate result")
    .baz
    .filter {...}
    .log()
    .qux
    .sort {...}

Which is good on the use site but I am not totally happy with the implementation side, specifically marking types Loggable.

Given there is no way to extend Any, is the above "log" the best I can do in current Swift?

Edited example and included a wiki link to "method chaining".

2 Likes

What are these chains for — are they sequences, Combine publishers, SwiftUI views? What you're describing as chains just seems like the functional-programming paradigm. Swift does allow users to adopt this paradigm, but since it's not universal (Swift also supports imperative programming, for example), you'll have to be more specific about what these chains do. So instead of marking things as Loggable, I suggest that you create a protocol that abstracts over the types you want to chain. Then, you may be able to make logging smarter and more efficient by printing specific information instead of relying on expensive, general-purpose reflection.