> On May 26, 2016, at 9:52 AM, Thorsten Seitz <[email protected]> wrote:
> 
>> 
>> Am 26.05.2016 um 15:40 schrieb Matthew Johnson <[email protected] 
>> <mailto:[email protected]>>:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>> On May 26, 2016, at 8:25 AM, Thorsten Seitz <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>> Ceylon requires checks whether cases are disjoint, i.e. when one case 
>>> contains a superclass of another case then this will be a type error „cases 
>>> are not disjoint“.
>>> 
>>> FWIW: Ceylon requires classes with enumerated subclasses to be abstract. 
>> 
>> Interesting, thanks for mentioning this.  The abstract requirement is what 
>> makes disjointedness at least partly possible (what if a subclass has 
>> further descendants though?).  But it still only works for a single level of 
>> inheritance:
>> 
>> sealed abstract class A {}
>> class B : A {}
>> class C : A {}
>> class D : B {}
>> class E : B {}
>> 
>> With a disjoint requirement I cannot ever match D and E because that would 
>> not be exhaustive and I am prohibited from matching them along side B which 
>> would be exhaustive but isn't disjoint.
> 
> Why?
> 
> switch a {
> case C: …
> case D: …
> case E: …
> }
> 
> is exhaustive because B has to be sealed as well (I would require this to be 
> declared explicitly).
> Abstractness seems not to be necessary for that IMO.
> Either you match against B *or* against all its subclasses.

In my example `B` is not abstract.  `a` might have dynamic type of `B` which 
would not match any of those cases.  You didn’t mention that you have to make 
all non-leaf classes `abstract` (or at least I didn’t understand that from what 
you wrote).  

I don’t like a design that requires non-leaf classes to be abstract.  First, it 
would require introducing abstract classes into Swift, which is a totally 
separate conversation and something I am not convinced is a good idea.  But it 
is also overly restrictive.  There are valid cases where you might want an 
exhaustive switch for a sealed hierarchy that has concrete parent classes.

If you want all non-leaf types to be abstract you should probably consider 
using protocols in Swift.  

> 
> Example in Ceylon:
> abstract class Parent() of Child1 | Child2 {}
> 
> class Child1() extends Parent() {}
> 
> abstract class Child2() of Grandchild1 | Grandchild2 extends Parent() {}
> 
> class Grandchild1() extends Child2() {}
> 
> class Grandchild2() extends Child2() {}
> 
> void main() {
>     Parent foo = Child1();
> 
>     switch (foo)
>     case (is Child1) {
>         print("Child1");
>     }
>     case (is Grandchild1) {
>         print("Grandchild1");
>     }
>     case (is Grandchild2) {
>         print("Grandchild2");
>     }
> }
> 
> -Thorsten
> 
>  
>> 
>> I don't think that solution is appropriate to Swift.  
>> 
>>> 
>>> -Thorsten
>>> 
>>>  
>>>> Am 25.05.2016 um 19:49 schrieb Matthew Johnson via swift-evolution 
>>>> <[email protected] <mailto:[email protected]>>:
>>>> 
>>>> 
>>>> 
>>>> Sent from my iPad
>>>> 
>>>> On May 25, 2016, at 12:41 PM, Charlie Monroe <[email protected] 
>>>> <mailto:[email protected]>> wrote:
>>>> 
>>>>>> Got it.  You could also say it is safer because you can't have a 
>>>>>> supertype case "swallow" a subtype value accidentally.  An "exact type" 
>>>>>> cast would prevent this possibility.
>>>>> 
>>>>> This still can be an issue since you still need to do the switch in 
>>>>> init(instance:), but it's just one place within the entire module, so it 
>>>>> can be more easily managed...
>>>> 
>>>> Yes, agree.  That's why your enum is safer.  I think we do need an exact 
>>>> type cast to prevent this problem.  'isExaclty' and 'asExactly' seem are a 
>>>> bit verbose but are very clear.  I can't think of anything I like that is 
>>>> more concise.
>>>> 
>>>>> 
>>>>>> 
>>>>>>> 
>>>>>>> enum AnimalSubclasses {
>>>>>>>         
>>>>>>>         case Dog
>>>>>>>         case Cat
>>>>>>> 
>>>>>>>         init(instance: Animal) {
>>>>>>>                 switch instance {
>>>>>>>                 case is Dog: self = .Dog
>>>>>>>                 case is Cat: self = .Cat
>>>>>>>                 default: fatalError("Unhandled instance \(instance)!")
>>>>>>>         }
>>>>>>> 
>>>>>>> }
>>>>>>> 
>>>>>>>> One thing I have considered that might also be worth introducing is an 
>>>>>>>> exact match cast.  This would prevent the possibility of putting a 
>>>>>>>> superclass case first and having it “steal” subclasses which were 
>>>>>>>> intended to be covered by a case later in the switch.  If we introduce 
>>>>>>>> exact match you would be able to write a switch that must always cover 
>>>>>>>> every concrete type, including all subclasses.  
>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> Charlie
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>> On May 25, 2016, at 4:41 AM, Leonardo Pessoa via swift-evolution 
>>>>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>>>> 
>>>>>>>>>> Limiting the amount of subclasses is not really a good idea as you 
>>>>>>>>>> would need to introduce another mechanism in the language while the 
>>>>>>>>>> proposed feature requires much less. And you're thinking only about 
>>>>>>>>>> the restrictive set (internal and private) and forgetting the more 
>>>>>>>>>> open end (public). Why is it so bad for this proposal to support 
>>>>>>>>>> requiring the default case? If its possible for the compiler to 
>>>>>>>>>> discover you covered all possible cases it would be fine not having 
>>>>>>>>>> default but IMHO in most cases it will find out there are more not 
>>>>>>>>>> explicitly covered.
>>>>>>>>>> From: David Sweeris <mailto:[email protected]>
>>>>>>>>>> Sent: ‎24/‎05/‎2016 11:01 PM
>>>>>>>>>> To: Austin Zheng <mailto:[email protected]>
>>>>>>>>>> Cc: Leonardo Pessoa <mailto:[email protected]>; swift-evolution 
>>>>>>>>>> <mailto:[email protected]>
>>>>>>>>>> Subject: Re: [swift-evolution] [Pitch] Exhaustive pattern matching 
>>>>>>>>>> forprotocols and classes
>>>>>>>>>> 
>>>>>>>>>> Or if there was a way to declare that a class/protocol can only have 
>>>>>>>>>> a defined set of subclasses/conforming types.
>>>>>>>>>> 
>>>>>>>>>> Sent from my iPhone
>>>>>>>>>> 
>>>>>>>>>> On May 24, 2016, at 15:35, Austin Zheng via swift-evolution 
>>>>>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>>>>>> 
>>>>>>>>>>> If you pattern match on a type that is declared internal or 
>>>>>>>>>>> private, it is impossible for the compiler to not have an 
>>>>>>>>>>> exhaustive list of subclasses that it can check against.
>>>>>>>>>>> 
>>>>>>>>>>> Austin
>>>>>>>>>>> 
>>>>>>>>>>> On Tue, May 24, 2016 at 1:29 PM, Leonardo Pessoa <[email protected] 
>>>>>>>>>>> <mailto:[email protected]>> wrote:
>>>>>>>>>>> I like this but I think it would be a lot hard to ensure you have 
>>>>>>>>>>> all
>>>>>>>>>>> subclasses covered. Think of frameworks that could provide many
>>>>>>>>>>> unsealed classes. You could also have an object that would have to
>>>>>>>>>>> handle a large subtree (NSObject?) and the order in which the cases
>>>>>>>>>>> are evaluated would matter just as in exception handling in 
>>>>>>>>>>> languages
>>>>>>>>>>> such as Java (or require some evaluation from the compiler to raise
>>>>>>>>>>> warnings). I'm +1 for this but these should be open-ended like 
>>>>>>>>>>> strings
>>>>>>>>>>> and require the default case.
>>>>>>>>>>> 
>>>>>>>>>>> On 24 May 2016 at 17:08, Austin Zheng via swift-evolution
>>>>>>>>>>> <[email protected] <mailto:[email protected]>> 
>>>>>>>>>>> wrote:
>>>>>>>>>>> > I have been hoping for the exhaustive pattern matching feature 
>>>>>>>>>>> > for a while
>>>>>>>>>>> > now, and would love to see a proposal.
>>>>>>>>>>> >
>>>>>>>>>>> > Austin
>>>>>>>>>>> >
>>>>>>>>>>> > On Tue, May 24, 2016 at 1:01 PM, Matthew Johnson via 
>>>>>>>>>>> > swift-evolution
>>>>>>>>>>> > <[email protected] <mailto:[email protected]>> 
>>>>>>>>>>> > wrote:
>>>>>>>>>>> >>
>>>>>>>>>>> >> Swift currently requires a default pattern matching clause when 
>>>>>>>>>>> >> you switch
>>>>>>>>>>> >> on an existential or a non-final class even if the protocol or 
>>>>>>>>>>> >> class is
>>>>>>>>>>> >> non-public and all cases are covered.  It would be really nice 
>>>>>>>>>>> >> if the
>>>>>>>>>>> >> default clause were not necessary in this case.  The compiler 
>>>>>>>>>>> >> has the
>>>>>>>>>>> >> necessary information to prove exhaustiveness.
>>>>>>>>>>> >>
>>>>>>>>>>> >> Related to this is the idea of introducing something like a 
>>>>>>>>>>> >> `sealed`
>>>>>>>>>>> >> modifier that could be applied to public protocols and classes.  
>>>>>>>>>>> >> The
>>>>>>>>>>> >> protocol or class would be visible when the module is imported, 
>>>>>>>>>>> >> but
>>>>>>>>>>> >> conformances or subclasses outside the declaring module would be 
>>>>>>>>>>> >> prohibited.
>>>>>>>>>>> >> Internal and private protocols and classes would implicitly be 
>>>>>>>>>>> >> sealed since
>>>>>>>>>>> >> they are not visible outside the module.  Any protocols that 
>>>>>>>>>>> >> inherit from a
>>>>>>>>>>> >> sealed protocol or classes that inherit from a sealed class 
>>>>>>>>>>> >> would also be
>>>>>>>>>>> >> implicitly sealed (if we didn’t do this the sealing of the 
>>>>>>>>>>> >> superprotocol /
>>>>>>>>>>> >> superclass could be violated by conforming to or inheriting from 
>>>>>>>>>>> >> a
>>>>>>>>>>> >> subprotocol / subclass).
>>>>>>>>>>> >>
>>>>>>>>>>> >> Here are examples that I would like to see be valid:
>>>>>>>>>>> >>
>>>>>>>>>>> >> protocol P {}
>>>>>>>>>>> >> // alternatively public sealed protocol P {}
>>>>>>>>>>> >> struct P1: P {}
>>>>>>>>>>> >> struct P2: P {}
>>>>>>>>>>> >>
>>>>>>>>>>> >> func p(p: P) -> Int {
>>>>>>>>>>> >>     switch p {
>>>>>>>>>>> >>     case is P1: return 1 // alternatively an `as` cast
>>>>>>>>>>> >>     case is P2: return 2 // alternatively an `as` cast
>>>>>>>>>>> >>     }
>>>>>>>>>>> >> }
>>>>>>>>>>> >>
>>>>>>>>>>> >> class C {}
>>>>>>>>>>> >> // alternatively public sealed class C {}
>>>>>>>>>>> >> class C1: C {}
>>>>>>>>>>> >> class C2: C {}
>>>>>>>>>>> >>
>>>>>>>>>>> >> func c(c: C) -> Int {
>>>>>>>>>>> >>     switch c {
>>>>>>>>>>> >>     case is C1: return 1 // alternatively an `as` cast
>>>>>>>>>>> >>     case is C2: return 2 // alternatively an `as` cast
>>>>>>>>>>> >>     case is C: return 0   // alternatively an `as` cast
>>>>>>>>>>> >>     }
>>>>>>>>>>> >> }
>>>>>>>>>>> >>
>>>>>>>>>>> >> I am wondering if this is something the community is interested 
>>>>>>>>>>> >> in.  If
>>>>>>>>>>> >> so, I am wondering if this is something that might be possible 
>>>>>>>>>>> >> in the Swift
>>>>>>>>>>> >> 3 timeframe (maybe just for private and internal protocols and 
>>>>>>>>>>> >> classes) or
>>>>>>>>>>> >> if it should wait for Swift 4 (this is likely the case).
>>>>>>>>>>> >>
>>>>>>>>>>> >> -Matthew
>>>>>>>>>>> >> _______________________________________________
>>>>>>>>>>> >> swift-evolution mailing list
>>>>>>>>>>> >> [email protected] <mailto:[email protected]>
>>>>>>>>>>> >> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>>>>> >> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>>>>> >
>>>>>>>>>>> >
>>>>>>>>>>> >
>>>>>>>>>>> > _______________________________________________
>>>>>>>>>>> > swift-evolution mailing list
>>>>>>>>>>> > [email protected] <mailto:[email protected]>
>>>>>>>>>>> > https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>>>>> > <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>>>>> >
>>>>>>>>>>> 
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> swift-evolution mailing list
>>>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>>> 
>>>>>>>>> _______________________________________________
>>>>>>>>> swift-evolution mailing list
>>>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to