[Pitch] consistent public access modifiers

Having loosely followed this discussion, the way I'm thinking of ‘closed’ is as a modifier which would let you switch over something from outside the module in which it is declared.

From outside the declaring module:
• A closed enum's cases can be exhaustively switched.
• A closed protocol's conforming types can be exhaustively switched.
• A closed class's subclasses can be exhaustively switched.

If this is correct, I can't help but think ‘closed’ is describing something subtly different in each case - picking and choosing the ‘important’ relationship for each type, while protocols already have a subtyping relationship, and it sounds like there's possibility for enum subtyping in the future.

I'd rather keep ‘open’ (and a potential future ‘closed’) purely describing the subtyping relationship, and have some other means of labelling conformance and cases as switchable.

Having loosely followed this discussion, the way I'm thinking of ‘closed’ is as a modifier which would let you switch over something from outside the module in which it is declared.

From outside the declaring module:
• A closed enum's cases can be exhaustively switched.
• A closed protocol's conforming types can be exhaustively switched.
• A closed class's subclasses can be exhaustively switched.

If this is correct, I can't help but think ‘closed’ is describing something subtly different in each case - picking and choosing the ‘important’ relationship for each type, while protocols already have a subtyping relationship, and it sounds like there's possibility for enum subtyping in the future.

I'd rather keep ‘open’ (and a potential future ‘closed’) purely describing the subtyping relationship, and have some other means of labelling conformance and cases as switchable.

I am drafting a manifesto-style document regarding value subtyping which will make it clear how value subtypes fit into the picture. This document covers the relationship of enum cases with value subtyping and will show clearly how enum cases are analogous to subclasses.

···

On Feb 13, 2017, at 11:28 AM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

This is definitely not correct. A "closed" enum's cases can be exhaustively switched from any module, but a non-open protocol's conforming types or non-open class's subclasses cannot be exhaustively switched from anywhere except the defining module (because there may be internal subclasses).

Jordan

···

On Feb 13, 2017, at 09:28, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Having loosely followed this discussion, the way I'm thinking of ‘closed’ is as a modifier which would let you switch over something from outside the module in which it is declared.

From outside the declaring module:
• A closed enum's cases can be exhaustively switched.
• A closed protocol's conforming types can be exhaustively switched.
• A closed class's subclasses can be exhaustively switched.

If this is correct, I can't help but think ‘closed’ is describing something subtly different in each case - picking and choosing the ‘important’ relationship for each type, while protocols already have a subtyping relationship, and it sounds like there's possibility for enum subtyping in the future.

I'd rather keep ‘open’ (and a potential future ‘closed’) purely describing the subtyping relationship, and have some other means of labelling conformance and cases as switchable.

I'm not sure how it fits your document, but I suspect value subtyping is pretty much not at all a source-compatibility or binary-compatibility concern. I think the only reasonable implementation here would be to perform conversions (unidirectional or bidirectional?), which means that the subtyping is almost entirely a client-side feature and the only potential dynamic operation would be using 'as?' with a generic type. This is very different from protocols and classes, which perform dynamic dispatch to method implementations present on their subtypes.

That is, the only effect of making a type "non-open" with respect to value subtyping would be to cut down on potential costs of 'as?'.

Jordan

···

On Feb 13, 2017, at 09:33, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

On Feb 13, 2017, at 11:28 AM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Having loosely followed this discussion, the way I'm thinking of ‘closed’ is as a modifier which would let you switch over something from outside the module in which it is declared.

From outside the declaring module:
• A closed enum's cases can be exhaustively switched.
• A closed protocol's conforming types can be exhaustively switched.
• A closed class's subclasses can be exhaustively switched.

If this is correct, I can't help but think ‘closed’ is describing something subtly different in each case - picking and choosing the ‘important’ relationship for each type, while protocols already have a subtyping relationship, and it sounds like there's possibility for enum subtyping in the future.

I'd rather keep ‘open’ (and a potential future ‘closed’) purely describing the subtyping relationship, and have some other means of labelling conformance and cases as switchable.

I am drafting a manifesto-style document regarding value subtyping which will make it clear how value subtypes fit into the picture. This document covers the relationship of enum cases with value subtyping and will show clearly how enum cases are analogous to subclasses.

Having loosely followed this discussion, the way I'm thinking of ‘closed’ is as a modifier which would let you switch over something from outside the module in which it is declared.

From outside the declaring module:
• A closed enum's cases can be exhaustively switched.
• A closed protocol's conforming types can be exhaustively switched.
• A closed class's subclasses can be exhaustively switched.

If this is correct, I can't help but think ‘closed’ is describing something subtly different in each case - picking and choosing the ‘important’ relationship for each type, while protocols already have a subtyping relationship, and it sounds like there's possibility for enum subtyping in the future.

I'd rather keep ‘open’ (and a potential future ‘closed’) purely describing the subtyping relationship, and have some other means of labelling conformance and cases as switchable.

I am drafting a manifesto-style document regarding value subtyping which will make it clear how value subtypes fit into the picture. This document covers the relationship of enum cases with value subtyping and will show clearly how enum cases are analogous to subclasses.

I'm not sure how it fits your document, but I suspect value subtyping is pretty much not at all a source-compatibility or binary-compatibility concern. I think the only reasonable implementation here would be to perform conversions (unidirectional or bidirectional?), which means that the subtyping is almost entirely a client-side feature and the only potential dynamic operation would be using 'as?' with a generic type. This is very different from protocols and classes, which perform dynamic dispatch to method implementations present on their subtypes.

That is, the only effect of making a type "non-open" with respect to value subtyping would be to cut down on potential costs of 'as?'.

Thanks for the replies Jordan. I haven't had a chance to closely look at your enum post yet - hopefully tomorrow.

I am not sure how relevant the ideas in my document are to language ABI but I suspect you are right that they are not very relevant there. I am less certain about the standard library (and haven't done any work to try and asses that either).

My thought is to share a manifesto-style document and ask the community to try to identify anything that might be relevant and keep the immediate conversation focused on that. The rest will have to wait until the time is right.

···

Sent from my iPad

On Feb 15, 2017, at 8:17 PM, Jordan Rose <jordan_rose@apple.com> wrote:

On Feb 13, 2017, at 09:33, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:
On Feb 13, 2017, at 11:28 AM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Jordan

Having loosely followed this discussion, the way I'm thinking of ‘closed’ is as a modifier which would let you switch over something from outside the module in which it is declared.

From outside the declaring module:
• A closed enum's cases can be exhaustively switched.
• A closed protocol's conforming types can be exhaustively switched.
• A closed class's subclasses can be exhaustively switched.

If this is correct, I can't help but think ‘closed’ is describing something subtly different in each case - picking and choosing the ‘important’ relationship for each type, while protocols already have a subtyping relationship, and it sounds like there's possibility for enum subtyping in the future.

I'd rather keep ‘open’ (and a potential future ‘closed’) purely describing the subtyping relationship, and have some other means of labelling conformance and cases as switchable.

I am drafting a manifesto-style document regarding value subtyping which will make it clear how value subtypes fit into the picture. This document covers the relationship of enum cases with value subtyping and will show clearly how enum cases are analogous to subclasses.

I'm not sure how it fits your document, but I suspect value subtyping is pretty much not at all a source-compatibility or binary-compatibility concern. I think the only reasonable implementation here would be to perform conversions (unidirectional or bidirectional?),

I meant to reply to this in my last message. Yes, the only sensible implementation I can think of is via conversion, which may be possible to optimize away in some cases where the supertype is representationally compatible with the subtype. Bidirectional conversion / inout wouldn't make sense. If you allow the supertype to mutate you may end up with a value that is not representable by the subtype.

···

Sent from my iPad

On Feb 15, 2017, at 8:17 PM, Jordan Rose <jordan_rose@apple.com> wrote:

On Feb 13, 2017, at 09:33, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:
On Feb 13, 2017, at 11:28 AM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

which means that the subtyping is almost entirely a client-side feature and the only potential dynamic operation would be using 'as?' with a generic type. This is very different from protocols and classes, which perform dynamic dispatch to method implementations present on their subtypes.

That is, the only effect of making a type "non-open" with respect to value subtyping would be to cut down on potential costs of 'as?'.

Jordan

Thanks for the correction, I hadn't considered that. Switching over subclasses/conformances could be quite a useful feature in itself, and with the way things are going it would likely need yet another access level…

···

On 16 Feb 2017, at 02:13, Jordan Rose <jordan_rose@apple.com> wrote:

On Feb 13, 2017, at 09:28, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Having loosely followed this discussion, the way I'm thinking of ‘closed’ is as a modifier which would let you switch over something from outside the module in which it is declared.

From outside the declaring module:
• A closed enum's cases can be exhaustively switched.
• A closed protocol's conforming types can be exhaustively switched.
• A closed class's subclasses can be exhaustively switched.

If this is correct, I can't help but think ‘closed’ is describing something subtly different in each case - picking and choosing the ‘important’ relationship for each type, while protocols already have a subtyping relationship, and it sounds like there's possibility for enum subtyping in the future.

I'd rather keep ‘open’ (and a potential future ‘closed’) purely describing the subtyping relationship, and have some other means of labelling conformance and cases as switchable.

This is definitely not correct. A "closed" enum's cases can be exhaustively switched from any module, but a non-open protocol's conforming types or non-open class's subclasses cannot be exhaustively switched from anywhere except the defining module (because there may be internal subclasses).

Jordan

Having loosely followed this discussion, the way I'm thinking of ‘closed’ is as a modifier which would let you switch over something from outside the module in which it is declared.

From outside the declaring module:
• A closed enum's cases can be exhaustively switched.
• A closed protocol's conforming types can be exhaustively switched.
• A closed class's subclasses can be exhaustively switched.

If this is correct, I can't help but think ‘closed’ is describing something subtly different in each case - picking and choosing the ‘important’ relationship for each type, while protocols already have a subtyping relationship, and it sounds like there's possibility for enum subtyping in the future.

I'd rather keep ‘open’ (and a potential future ‘closed’) purely describing the subtyping relationship, and have some other means of labelling conformance and cases as switchable.

This is definitely not correct. A "closed" enum's cases can be exhaustively switched from any module, but a non-open protocol's conforming types or non-open class's subclasses cannot be exhaustively switched from anywhere except the defining module (because there may be internal subclasses).

Jordan

Thanks for the correction, I hadn't considered that. Switching over subclasses/conformances could be quite a useful feature in itself, and with the way things are going it would likely need yet another access level…

This could be facilitated by the proposal I put forward that started this thread. The idea is to put enums, classes and protocols on more equal footing. I used the term `closed` in the sense that it is typically used for enums, but also allow it to be used with classes and protocols which may be exhaustively switched over. I used `public` in the sense that we say “resilient enum”, `public class` or “non-open” protocol. Finally, I expanded the use of `open` to also be applicable to protocols and user-extensible enums.

It will probably be more clear after I share my manifesto on value subtyping (coming very soon), but the perspective underlying this idea is that we have three different kinds of types which may have concrete subtypes: enums (enhanced as I will demonstrate in my value subtyping manifesto), classes and protocols. With this in mind, it seems wise (to me at least) to establish common syntax and semantics for controlling how new concrete subtypes may be introduced (by users of a module, by future versions of the module, etc).

···

On Feb 16, 2017, at 8:21 AM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

On 16 Feb 2017, at 02:13, Jordan Rose <jordan_rose@apple.com> wrote:

On Feb 13, 2017, at 09:28, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution