That's my dilemma here. Since this particular case has literally no payload, it should never return anything. Either that, or we want to express "nothing" as Void here. That's the clarification I'm seeking for.
Well Optional<Void> and Bool are isomorphic, and if we want a general API for all enum cases, testing for != nil is equivalent to testing for == true.
We either have to drop support for them altogether (don't mind using Never over Void, they could simply not be available at all), or special-case bare cases with Bool, or use Void — as suggested!
But the "case" key path has two purposes: (1) To test if the value matches a certain case, and (2) to extract the payload if it does. If you could not return a valid value for "the cases matches and it has no payload", the API would not be able to perform its first purpose.
In the following enum, item1a and item1b are equivalent. If the payload would be Never, it would not be possible to create a value of that case.
enum Foo {
case item0(Never) // 0 possible values. This case is impossible to create.
case item1a // 1 possible value
case item1b(Void) // 1 possible value
case item2(Bool) // 2 possible values
}
It seems correct to me to have Void as the payload of a case without a (specified) payload.
Actually, item1a and item1b were deliberately made distinct in one of the previous enum proposals. It would be good to be consistent on this with keypaths.
Anyway, let's avoid derailing the is case thread regarding this distinct, not-yet-pitched idea.
For sure! I think it's really important to keep in mind both alternatives and features that might partially overlap or complement the currently pitched idea.
But this is distinct from getting into the detailed design of those alternatives or related features particularly as it relates to aspects that wouldn't affect this idea. It's been well over a dozen messages getting ever deeper in this direction.
I would suggest splitting off the parts of the thread that concern the design of case paths, but it also seems unfair to start discussing a design when the authors haven't got it to a place where they're ready to pitch it.
Right. This all started because Joe correctly pointed out that the motivation for is case would be a lot lower if there were an existing way to test if an enum value had a particular case, and that several of the alternative ways proposed for this in the past have been more powerful too. (In particular, they'd provide a way to get at an enum payload in expression context, which is case does not.) Past proposed alternatives I know of include
implicitly synthesized properties, possibly opt-in (mentioned in the current is case write-up)
In practice, I agree that we might not bother with is case if we had one of these features already. However, I do think that is case is much more tractable. We've had seven and a half years of open-source Swift and none of the proposals have been implemented for a proper review; is case is the simplest to implement; the simplest to document and teach; has the simplest compatibility story; and will remain useful even if we get one of the other features later.
This is an elegant solution to a very common sugar problem, best one so far! But I wonder if there would be a way to also support what others here have mentioned, namely checking if two instances of an enum are the same case. Something like:
enum MyEnum {
case one(Double)
case two(Int)
}
func sameCase(x: MyEnum, y: MyEnum) -> Bool {
case x == case y
}
This would see case as an operator that turns an instance of MyEnum into an instance of the synthesized MyEnum.Discriminant:
extension MyEnum {
enum Discriminant {
case one
case two
}
}
I feel that this enum and the operator could be generally useful, but I'm not sure how it plays with the proposal here.
I'd be interested to tackle this implementation but I don't have any experience with the compiler. Would anyone be able to provide any pointers on how to approach this?