A Possible Vision for Macros in Swift

This can be accomplished today (without resorting to C) with package manager plugins that generate a Swift source file for inclusion in the build, either with something like Sourcery or just a hardcoded template.

I worry about making macros too powerful, as they're generally pretty difficult to read in most languages I've encountered them (C, Rust, Verilog, etc.). I think there definitely is a need for some additional macro functionality*, but in my own opinion the combination of build plugins, some additional work on things like function wrappers, and build-time constants can solve the majority of metaprogramming needs without opening the can of worms that is a fully-featured macro system.

For instance, I am pretty strongly against things from the linked document like:

  • #localCleanup("file", File(opening: "hello.txt"))
  • #colorLiteral(red: 0.5, green: 0.5, blue: 0.25, alpha: 1.0)
  • func assert(#stringify _ result: Bool)

I get that such macros centralize some boilerplate, but they make the code that much harder to reason about for a pretty minor simplification - now you have to go find the underlying macro definition to understand each of those. Put another way, if we need to resort to macros to accomplish each of those examples that might instead be a sign we need additional language features/standard library functionality instead (in the case of the first example above, something like a Python-style context manager could provide similar functionality). I'd also be quite concerned with the effect these would have on code-completion and other developer tools.

Maybe the core features and style of Swift will lend itself well to encouraging programmers to be more disciplined with how they use macros, but I've seen one too many macro-filled spaghetti-code C/Verilog codebases to think that opening the door to such a powerful set of features won't result in a net decrease in code readability.

* Things that definitively fall into this category for me are memberwise initializer generation and generalizing automatic protocol conformances like for Codable/Equatable/etc.. I don't know how you provide the tools to implement those without also opening the door to macro "abuse", but I'd be very much in favor of a more limited macro system that was basically only able to synthesize methods/computed properties from a type's stored properties.

17 Likes