[swift-evolution] [Pitch] Exhaustive pattern matching for protocols and classes
Leonardo Pessoa
me at lmpessoa.com
Wed May 25 17:52:27 CDT 2016
On Wednesday, 25 May 2016, Matthew Johnson <matthew at anandabits.com> wrote:
>
>
> Sent from my iPad
>
> On May 25, 2016, at 12:04 PM, Leonardo Pessoa via swift-evolution <
> swift-evolution at swift.org
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>> wrote:
>
> I like the idea of sealed types but I think much better is Ceylon's
> concept of previously declaring the many subclasses that are going to exist
> both because I can have a bunch of public classes in a framework and
> restrict their subclasses and because there are threads in this group
> discussing the idea of a union type (perhaps both ideas could benefit from
> one another).
>
>
> I think there are reasonable arguments both for and against forcing the
> programmer to declare all subclasses in one location. The argument for it
> is that it provides documentation value by listing all possible cases in
> the same place. The argument against it is that this could get annoying as
> you add subclasses inside the module and the compiler will tell you when
> you miss a case in your switches anyway.
>
>
Actually this "annoyance" is a good part as any other warning you get from
the compiler in any situations to tell you something is wrong in your code
and needs fixing.
>
>
> Another idea could be to add a single simple keyword to the root class
> (could even be sealed but I don't think it grabs this concept) to declare
> all its subclasses must exist within the same module. That would restrict
> the number of subclasses to the compiler without requiring us to revisit
> the root class each time we need to create a subclass and would still allow
> for every subclass to be public.
>
>
> Sealed wouldn't be a good idea because the root class would still enable
> subclassing and it would be ideal that the switch could only work with
> these "sealed" types.
>
>
> I proposed 'sealed' for this using the definition we have seen previously
> on the list - closed to inheritance outside the module. It doesn't mean
> 'final'.
>
>
> +1 for enabling this for protocols too.
>
> Just a few issues:
> - here we're considering having subclasses of subclasses, or not?
>
>
> Yes, as long as they're within the same module as the 'sealed' type.
>
> -what about public protocols being adopted outside the module, should we
> just ignore them or completely forbid the adoption?
>
>
> The ability to have 'public sealed' is the only reason to have 'sealed' at
> all. 'private' and 'internal' are implicitly 'sealed' by lack of external
> visibility. If your users need to be able to conform to your protocol you
> wouldn't be able to make it 'sealed' and would have to include the default
> clause in a switch statement. 'sealed' is for times where your design
> requires a fixed set of conformances that are all packed together in the
> same module as the protocol, but the protocol must be visible publicly.
>
>
> ------------------------------
> From: Thorsten Seitz via swift-evolution
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>
> Sent: 25/05/2016 01:18 PM
> To: Thorsten Seitz <javascript:_e(%7B%7D,'cvml','tseitz42 at icloud.com');>
> Cc: swift-evolution
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>
> Subject: Re: [swift-evolution] [Pitch] Exhaustive pattern matching
> forprotocols and classes
>
> Just realized that Matthew did introduce `sealed` exactly to enable this
> for public types. That's fine with me!
>
> -Thorsten
>
> Am 25.05.2016 um 18:11 schrieb Thorsten Seitz via swift-evolution <
> swift-evolution at swift.org
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>>:
>
> Ceylon uses the following syntax for stating that a class has a finite set
> of subclasses:
>
> class C of C1 | C2 {...}
>
> where `|` is the type union operator. Swift could use a simple comma
> separated list instead after the `or`. The advantage over
> sealed+private/internal would be thatnthe class or protocol could be public
> as well.
>
> -Thorsten
>
> Am 25.05.2016 um 04:01 schrieb David Sweeris via swift-evolution <
> swift-evolution at swift.org
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>>:
>
> 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 <
> swift-evolution at swift.org
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>> 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 <me at lmpessoa.com
> <javascript:_e(%7B%7D,'cvml','me at lmpessoa.com');>> 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
>> <swift-evolution at swift.org
>> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>> 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
>> > <swift-evolution at swift.org
>> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>> 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
>> >> swift-evolution at swift.org
>> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>
>> >> https://lists.swift.org/mailman/listinfo/swift-evolution
>> >
>> >
>> >
>> > _______________________________________________
>> > swift-evolution mailing list
>> > swift-evolution at swift.org
>> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>
>> > https://lists.swift.org/mailman/listinfo/swift-evolution
>> >
>>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> <javascript:_e(%7B%7D,'cvml','swift-evolution at swift.org');>
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
--
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160525/c234ce83/attachment.html>
More information about the swift-evolution
mailing list