SE-0415: Function Body Macros

…but body macros cannot be composed together, so you can't have e.g. @Logged and @Traced on the same function, or either in combination with @Retrying etc.

That's a pretty notable limitation.

Could preamble macros be replaced with wrapper macros, which essentially expand like:

@Logged
func g(a: Int, b: Int) throws -> Int {
   try add(a, b)
}

…to:

func g(a: Int, b: Int) throws -> Int {
    log("Entering g(a: \(a), b: \(b))")

    do {
        let result = try {
            try add(a, b)
        }()

        log("Exited g(a: \(a), b: \(b)) with result: \(result)")
        return result
    } catch {
        log("Exited g(a: \(a), b: \(b)) with error: \(error)")
        throw error
    }
}

These compose more neatly since they naturally nest.

You can also see why it's highly desirable to have a macro for things like this, because there's quite a lot of boilerplate for this simple pattern.

3 Likes