In my own code I do a similar thing, but would love it if Swift supported this as a sort of special identity inquiry. I refer to it in my own stuff as “celf” (case-self) and mock variables to handle it much how you do with an inner enum stripped down without values, but would love if something like this was feasible without boilerplate
enum CelfRepresenting {
case a(Int)
case b(Double)
case c(String)
enum CaseSelf {
case a
case b
case c
}
var celf: CaseSelf {
switch self {
case .a: return .a
case .b: return .b
case .c: return .c
}
}
}
let x: CelfRepresenting = .a(42)
Print(x.celf == .a) // true
Aside from convenience, it cuts down on unwrapping enums in cases where I don’t care about the value and (personally) find the brevity a huge help as I’m usually doing that in conditionals where it clutters legibility, IMO.
Also allows use of it in ternary operators, which I favor, and would be great for things like hardcoding fast paths in more involved enums
let x = Set<MyEnum.celf>(.a, .b, .c, —- .z)
…
let y = MyEnum.f(ComplexObject)
x.contains(y.celf) ? easyCalc(y) : slowCalc(y)
Nevertheless, I'm not against the principle of this pitch. There's still plenty to explore in this particular area and I'm very strongly in favor of these mechanisms being baked into the language itself.
I think the conversation got sidetracked on the Codable stuff, but I was essentially just proposing auto-synthesised cases for enums with associated types.
I think IntCase and StringCase provide much more flexibility. It's nice to know the index/name of the enum case when handling custom Codable implementations.
We wrote the library because Swift doesn't come with case paths / enum key paths, but we would be more than happy to retire it if someone gets an implementation working! We'd even be happy to help write the pitch and work out some of the design details.
This is exactly what case paths was born out of. We use them heavily in swift-composable-architecture. They're useful for far more, though. Even "vanilla" SwiftUI benefits, since it gives you the ability to derive bindings of enum cases from bindings of enums.
If there's other pitches then I'd say it's got traction as something the developers want in the language, or at least those of us willing to pitch it, so perhaps we should see if we can move it along into a real pitch?
And in an even more general sense, a lot of these things could be unlocked if the reflection capabilities of the language were better. By bringing over more "knowledge" from the compiler onto the language, Swift would enable so many of these capabilities by third parties to flourish — and potentially be added onto the language officially, if uptake is positive.
IMHO reflection is the bottleneck that needs addressing.
Sure: structural generic programming capabilities are reflection. But it is not just any old reflection that's needed—it's reflection that can interact with the type system, which is what you need for synthesizing conformances and associated types. That's what the structural generic programming proposal provides.
The structural generic programming proposal is interesting, but I'd hesitate to say that it's the best way we can expose that information to the type system. Variadic generics will likely improve how these things can be represented - e.g. a struct's members can be represented as a variadic list of parameters, presumably there'd be ways to write extensions and protocol conformances if all parameters met some constraints, etc.
Variadic generics will likely improve how these things can be represented
Yes, I take it for granted that programming with the kinds of type structures in the structural generic programming proposal would be improved with variadic generics, and I look forward to the introduction of those features with antici… pation. The basic approach is still valid, and could subsume many one-off language extension proposals such as this one, and most ideas for general reflection.
CasePaths used to use reflection, but using a mirror is about 1,000x slower than manually writing an if case let. This may not be a big deal for a casual match/extraction, but can add up quickly in a hot code path. These days CasePaths uses the Swift runtime metadata, instead, and is only about 2–5x slower than an if case let.
As nice as it is to have runtime metadata around to implement this functionality ourselves in a performant-enough way, this really is a feature that should be built into the language, given that key paths are built into the language and are used all over the place these days, like all of the dynamic member lookups in SwiftUI.
I would love to see CasePaths introduced as a language feature (as well as Enum properties). The discrepancy in ergonomics between Structs and Enums is probably the area where I'd most frequently benefit from quality of life improvements, and in my experience a non-negligible source of friction to the more wider adoption of safer, more unambiguous patterns/architectures in Swift codebases.
IMHO, in SwiftUI (and almost every other language in which it's used) Redux-style systems are fine for small apps, but one they reach a certain size you start having to worry about performance issues cropping up on every state change, as making a global state change every single time the user does anything ends up causing the app to diff the entire view tree looking for changes.
Local state, MVVM, and micro-service architectures are much more suited to SwiftUI than Redux.
I know architectures are like religion, but the amount of workarounds that seem to be needed to alleviate your pain points (including requesting changes to Swift itself) seem to me to be a great example of why Redux-style systems are NOT perfect for SwiftUI. It's simply not how it was built.