Macros in Swift?

MacrosSwift

Macros Problem Overview


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.

Macros Solutions


Solution 1 - Macros

In this case you should add a default value for the "macro" parameters.

Swift 2.2 and higher

func log(message: String,
        function: String = #function,
            file: String = #file,
            line: Int = #line) {

     print("Message \"\(message)\" (File: \(file), Function: \(function), Line: \(line))")
}

log("Some message")

Swift 2.1 and lower

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

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

log("Some message")

This is what fatalError and assert functions do.

There are no other macros except the conditional compilation already mentioned in another answer.

Solution 2 - Macros

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 3 - Macros

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

Solution 4 - Macros

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 5 - Macros

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 6 - Macros

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 7 - Macros

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 8 - Macros

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjhurlimanView Question on Stackoverflow
Solution 1 - MacrosSulthanView Answer on Stackoverflow
Solution 2 - MacrosColinEView Answer on Stackoverflow
Solution 3 - MacrosglencView Answer on Stackoverflow
Solution 4 - MacrosDaniel RyanView Answer on Stackoverflow
Solution 5 - MacrosAlan EdmondsView Answer on Stackoverflow
Solution 6 - Macrosabdul satharView Answer on Stackoverflow
Solution 7 - MacrosNikolai IschukView Answer on Stackoverflow
Solution 8 - Macrosuser19076664View Answer on Stackoverflow