That macro generates is<case>
declarations for each enum case, like this:
@CaseDetection // opt-in macro
enum Destination {
case inbox
case messageThread(id: Int)
}
// Generated code:
extension Destination {
var isInbox: Bool { ... }
var isMessageThread: Bool { ... }
}
I'm really excited about macros, but there are a few reasons why I think this sort of macro isn't the right solution here:
Even if the macro was defined in the standard library, actually adopting the macro on your enum is op-in, so this would only be usable in cases where the author of the enum declaration opted-in to this functionality.
Other code synthesis functionality like this is typically opt-in (e.g. CaseIterable
) but that's because the code synthesis adds a new semantic guarantees that the author needs to consider going forwards. This isn't the case with something like @CaseDetection
, since it doesn't impose any additional semantic requirements.
Any solution here would ideally be supported by default for all enum declarations, so users have a consistent way of working with all enum values across their entire project. But even if we could force this macro to be applied to all enum declarations, I don't think we would want to -- the generated properties would result in a large code size increase.
This is why an operator at the call site, like <expr> is case <pattern>
, makes the most sense to me.
That being said, I could imagine using a macro defined in the standard library that we use in place of an is case
operator. For example:
let destination = Destination.messageThread(id: 42)
print(@isCase(destination, .inbox)) // false
print(@isCase(destination, .messageThread)) // true
// Generates:
let destination = Destination.messageThread(id: 42)
print({ if case .inbox = destination { true } else { false }}()) // false
print({ if case .messageThread = destination { true } else { false }}()) // true
That's definitely a neat option with a majority of the benefits of defining a new operator. I find this significantly less idiomatic than an operator, though, particularly since it's a free function.