'Macros in Swift?

Does Swift currently support macros, or are there future plans to add support? Currently I'm scattering:

Log.trace(nil, function: __FUNCTION__, file: __FILE__, line: __LINE__)

In various places throughout my code.



Solution 1:[1]

The Apple docs state that:

Declare simple macros as global constants, and translate complex macros into functions.

You can still use #if/#else/#endif - but my feeling is that they will not introduce macro functions, the language simply doesn't need it.

Solution 2:[2]

Since XCode 7.3, the __FILE__ __FUNCTION__ and __LINE__ compile-time constants have become the nicer-looking #file #function and #line respectively.

Solution 3:[3]

Here is an updated Swift 2 answer.

func LogW(msg:String, function: String = #function, file: String = #file, line: Int = #line){
    print("[WARNING]\(makeTag(function, file: file, line: line)) : \(msg)")
}

private func makeTag(function: String, file: String, line: Int) -> String{
    let url = NSURL(fileURLWithPath: file)
    let className = url.lastPathComponent ?? file
    return "\(className) \(function)[\(line)]"
}

Example of use:

LogW("Socket connection error: \(error)")

Solution 4:[4]

lastPathComponent needs an NSURL, so I changed the above code to this:

func log(message: String,
    function: String = __FUNCTION__,
    file: String = __FILE__,
    line: Int = __LINE__) {

        let url = NSURL(fileURLWithPath: file)

        print("Message \"\(message)\" (File: \(url.lastPathComponent ?? "?"), Function: \(function), Line: \(line))")
}

log("some message")

Solution 5:[5]

There is way to use macros on swift (but this used in Mixed of objective c and swift)

declare your macros into Project-name-Bridging-Header.h

#define  YOUR_MACRO @"Description"

or create separate header file for macros "macros.h"

import this header "macros.h" in to your Bridging-Header.h file..

now just save your project your macros will came in swift file ..

if you don't wanna object c code on your swift project... just create dummy cocoa touch classes it will create bridging header then use my way...

Solution 6:[6]

Macros are evil, but sometimes you just need them. For example, I have

struct RegionEntity {
    var id: Int!
}

And I want to place instances of this struct to Set. So I have to conform it to Hashable protocol.

extension RegionEntity: Hashable {
    public var hashValue: Int {
        return id
    }
}

public func ==(first: RegionEntity, second: RegionEntity) -> Bool {
    return first.id == second.id
}

Great. But what if I have dozens of such structs and the logic is the same? Maybe I can declare some protocol and conform it to Hashable implicitly. Let's check:

protocol Indexable {
    var id: Int! { get }
}

extension Indexable {
    var hashValue: Int {
        return id
    }
}

func ==(first: Indexable, second: Indexable) -> Bool {
    return first.id == second.id
}

Well, it works. And now I'm gonna conform my struct to both protocols:

struct RegionEntity: Indexable, Hashable {
    var id: Int!
}

Nope. I can't do that, because Equatable requires == operator with Self and there is no == operator for RegionEntity. Swift forces me to copy-paste confirmation code for each struct and just change the name. With macro I could do that with only one line.

Solution 7:[7]

Swift doesn't support macros because it would conflict with type-safety.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ColinE
Solution 2 glenc
Solution 3
Solution 4 Alan Edmonds
Solution 5 abdul sathar
Solution 6 Nikolai Ischuk
Solution 7 user19076664