|
1 |
| -# Replace `protocol<P1,P2>` syntax with `Any<P1,P2>` |
| 1 | +# Replace `protocol<P1,P2>` syntax with `P1 & P2` syntax |
2 | 2 |
|
3 | 3 | * Proposal: [SE-0095](0095-any-as-existential.md)
|
4 | 4 | * Author: [Adrian Zubarev](https://github.com/DevAndArtist), [Austin Zheng](https://github.com/austinzheng)
|
5 |
| -* Status: **Returned for Revision** [Rationale](https://lists.swift.org/pipermail/swift-evolution-announce/2016-June/000182.html) |
| 5 | +* Status: **TBD** |
6 | 6 | * Review manager: [Chris Lattner](http://github.com/lattner)
|
| 7 | +* Revision: 2 |
| 8 | +* Previous Revisions: [1](https://github.com/apple/swift-evolution/blob/a4356fee94c06181715fad83aa61e923eb73f8ec/proposals/0095-any-as-existential.md) |
7 | 9 |
|
8 | 10 | ## Introduction
|
9 | 11 |
|
10 |
| -The current `protocol<>` construct, which defines an existential type consisting of zero or more protocols, should be renamed `Any<>`. |
| 12 | +The current `protocol<>` construct, which defines an existential type consisting of zero or more protocols, should be replaced by an infix `&` type operator joining bare protocol type names. |
11 | 13 |
|
12 |
| -[Discussion thread](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160516/018109.html) |
| 14 | +Discussion threads: [pre-proposal](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160516/018109.html), [review thread 1](http://thread.gmane.org/gmane.comp.lang.swift.evolution/18349), [2](http://thread.gmane.org/gmane.comp.lang.swift.evolution/18350/focus=18447), [3](http://thread.gmane.org/gmane.comp.lang.swift.evolution/18351/focus=18440), [4](http://thread.gmane.org/gmane.comp.lang.swift.evolution/18518), [post-review thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/19463) |
13 | 15 |
|
14 | 16 | ## Motivation
|
15 | 17 |
|
16 | 18 | A stated goal for Swift 3.0 is making breaking changes to prepare the way for features to be introduced in future features, especially those involving the enhancements to the generics system detailed in [*Completing Generics*](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md).
|
17 | 19 |
|
18 |
| -One such change described in *Completing Generics* is renaming `protocol<>` to `Any<>` in order to allow it to serve as a syntactic foundation for more generalized existential types. This is a straightforward change which will allow a later version of Swift to introduce better handling for existential types without making breaking changes, or changes whose functionality overlaps with that of existing features. |
| 20 | +One such change described in *Completing Generics* is improving the existing `protocol<>` syntax in order to allow it to serve as a syntactic foundation for more generalized existential types. This is a straightforward change which will allow a later version of Swift to introduce better handling for existential types without making breaking changes, or changes whose functionality overlaps with that of existing features. |
19 | 21 |
|
20 | 22 | ## Proposed solution
|
21 | 23 |
|
22 |
| -The `protocol<...>` construct should be replaced with the `Any<...>` construct, where one or more protocol names can be inserted between the angle brackets to denote protocol composition. There will be no changes to the behavior of `Any<...>` relative to `protocol<...>`. |
| 24 | +The `protocol<...>` construct should be removed. In its place, an infix type operator `&` will be introduced. |
23 | 25 |
|
24 |
| -`Any` will retain the same function and behavior as it did prior to Swift 3.0. `Any<>` will be forbidden. An error message can direct users to use `Any` instead of `Any<>`. |
| 26 | +An existential type comprised of more than one protocol will be defined by listing its types, separated by the `&` operator, as shown below in the examples. |
| 27 | + |
| 28 | +The existing `Any` typealias, which represents all types that conform to zero or more protocols (i.e. all types), will become a keyword. Its meaning will not change. |
25 | 29 |
|
26 | 30 | Trivial example:
|
27 | 31 |
|
28 | 32 | ```swift
|
29 | 33 | protocol A { }
|
30 | 34 | protocol B { }
|
| 35 | +protocol C { } |
31 | 36 |
|
32 |
| -struct Foo : A, B { } |
| 37 | +struct Foo : A, B, C { } |
33 | 38 |
|
34 |
| -let a : Any<A, B> = Foo() |
| 39 | +let a : A & B & C = Foo() |
35 | 40 | ```
|
36 | 41 |
|
37 |
| -## Impact on existing code |
38 |
| - |
39 |
| -Programmers will need to update any code using `protocol<...>` (this can be done with a simple find and replace operation). Code that uses `Any`, but no protocol composition, will be unaffected. Code that happens to use `protocol<>` must be changed to use `Any` instead. |
40 |
| - |
41 |
| -## Alternatives considered |
42 |
| - |
43 |
| -A couple of alternative options for proposal details follow. |
44 |
| - |
45 |
| -* The original proposal allowed both `Any<>` and `Any`. However, community members brought up concerns regarding the fact that there were two nearly-identical representations for the 'any type' existential, and that there could possibly be issues cleanly defining the grammar or implementing the parser to properly handle both cases. |
| 42 | +Example with functions: |
46 | 43 |
|
47 |
| -### `Any` vs `any` |
| 44 | +```swift |
| 45 | +protocol A { } |
| 46 | +protocol B { } |
48 | 47 |
|
49 |
| -A discussion took place among swift-evolution participants as to whether or not the keyword for this feature should be `Any` or `any`. This proposal presents `Any`, but also lists reasons provided in favor of both options below, with the hope that the proposal review discussion and core team can choose the best option. |
| 48 | +// Existential |
| 49 | +func firstFunc(x: A & B) { ... } |
50 | 50 |
|
51 |
| -**For `Any<P1, P2>`**: |
| 51 | +// Generic |
| 52 | +func secondFunc<T : A & B>(x: T) { ... } |
| 53 | +``` |
52 | 54 |
|
53 |
| -* The convention is to capitalize types. `Any<A, B>` is immediately apparent as a type, and looks like a type when used in places where types would be used (like function signatures). |
54 |
| -* Having `Any<A, B>` allows us to keep the well-established `Any` without having to typealias to `any` or `any<>` forms. |
55 |
| -* `any` is a keyword, but an argument can be made that keywords that fit into a particular syntactic slot should be capitalized like normal members of that slot. `Any<...>` fits into the slot of identifiers used as types, so it should be named like a type. |
56 |
| -* In the future, `AnySequence` and similar type-erased wrappers can be replaced with, e.g. `Any<Sequence>`. This increases discoverability of existential features, like a future `Any<Sequence where .Element == String>`. It's possible this will increase awareness and use of `Any<...>` over that of `protocol<>`, which is difficult to discover. |
| 55 | +The use of `&` instead of `,` more clearly conveys the intent of the syntactic construct: defining a composite type formed from the conjunction of two or more protocol types. |
57 | 56 |
|
58 |
| -**For `any<P1, P2>`**: |
| 57 | +## Impact on existing code |
59 | 58 |
|
60 |
| -* `any<...>`'s lower case 'a' distinguishes it from other generic types that use similar syntax, such as `Array<Int>`. Perhaps developers, especially those new to Swift, will be confused as to why `Any<A, B>` isn't a generic type, but `Dictionary<A, B>` is. Even without considering new developers, it can be jarring to have to mentally make the context switch between `Any<A, B>` as an existential, and `AnythingButAny<A, B>` as a generic type. |
61 |
| -* `any<...>`'s lower case 'a' makes it clear to users it is not equivalent to a standard user-defined type, but rather a construction that can be used as a type in some cases, and can't be used everywhere a user-defined type can. |
62 |
| -* `any<...>` isn't a specific type - it's a kind of type (an existential), and this spelling fits better with the other 'kind' names: `class`, `struct`, `enum`, `protocol` |
63 |
| -* `any` is a keyword, and a convention has been established that keywords are lower case without initial or CamelCase-style capitalization. It is important to be consistent in this matter. |
| 59 | +Programmers will need to update any code using `protocol<...>`. Code that uses `Any`, but no protocol composition, will be unaffected. Code that happens to use `protocol<>` must be changed to use `Any` instead. |
64 | 60 |
|
65 |
| -### Alternatives to entire proposal |
| 61 | +## Future directions |
66 | 62 |
|
67 |
| -A couple alternatives to this entire proposal follow. |
| 63 | +Whenever a [generalized existential](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials) proposal is prepared, the syntax established by this proposal can be extended as appropriate to cover additional functionality (such as `where` clauses). |
68 | 64 |
|
69 |
| -* Leave `protocol<>` as-is, and decide whether to change it after Swift 3.0 ships. This has the disadvantage of introducing a breaking source change. |
| 65 | +## Alternatives considered |
70 | 66 |
|
71 |
| -* Decide before Swift 3.0 ships that generalized existentials should be defined using a syntax besides the `protocol<>` or `Any<>` syntaxes, and adopt that syntax instead. Disadvantages: core team has no bandwidth to consider changes of this scope at the current time. |
| 67 | +The original proposal suggested replacing `protocol<>` with either `Any<>` or `any<>`. |
72 | 68 |
|
73 | 69 | ## Acknowledgements
|
74 | 70 |
|
75 |
| -[Matthew Johnson](https://github.com/anandabits) and [Brent Royal-Gordon](https://github.com/brentdax) provided valuable input which helped shape this proposal. |
| 71 | +[Matthew Johnson](https://github.com/anandabits) and [Brent Royal-Gordon](https://github.com/brentdax) provided valuable input which helped shape the first version of this proposal. |
76 | 72 |
|
77 | 73 | -------------------------------------------------------------------------------
|
78 | 74 |
|
|
0 commit comments