swiftxcode

Using special literals in a function


I’m trying to write a wrapper for the print() function which also includes the current line number. I have something like this:

//  wrapper around print:
    func dbug(_ things: Any...) {
        print("\(#line): ",  things.map {"\($0)"}.joined(separator: ", "))
    }

//  elsewhere:
    dbug("hello", 23)

The only problem is that the #line literal prints the line number within the function, not the line number where it’s called, which is a bit of a waste of time.

Short of adding #line at the source, is there a way of getting the line number where the function is called?


Solution

  • Instead of using the #line macro in the function body, add an extra parameter and use #line as the default value of that parameter.

    func dbug(_ things: Any..., line: UInt = #line) {
        print("\(line): ",  things.map {"\($0)"}.joined(separator: ", "))
    }
    
    // usage:
    dbug("hello", "something else") // don't pass the 'line' parameter!
    

    Then this works out of the box, because macros that are used as default values expand on the caller's side.

    You can see the same pattern used in many built-in functions, like preconditionFailure, fatalError, etc.