I'm honestly not sure it makes sense to introduce a proposal just for 
expressing <Class, Protocol, Protocol> style requirements, and then trying to 
retrofit fuller support for other existentials onto it. I would prefer that the 
'basic package' of existential cases be considered together as a single 
proposal, unless a core team member expresses their preference otherwise.

I don’t see the point why we couldn’t do that! I mean if we add to much into a 
single proposal it would have more chances to be rejected. Besides that Chris 
already did the same with his `generic typealias` proposal where the whole 
feature was only introduced in its base form, which will gain more constraints 
later on. I don’t think the base form of `Any<>` gaining more constraints will 
break any code later, when there are no significant changes in syntax.

Another area you didn’t touch on is whether Any constructs (and typealiases 
referring to them) should be usable as generic constraints.  I would expect 
this to be possible but I think we need to spell it out.
I was thinking about this while looking at `var view: Any<UIView, 
SomeProtocol>`. If UIView does not conform to SomeProtocol you won’t be able to 
construct that type because otherwise it just would be `UIView`.

One would only be able to construct `Any<>` if it can be inferred to a single 
type like `SomeClass`. Thats what I thought and dropped from mentioning that. 



Btw. I submitted a pull request already, but I noted in my proposal in the 
future directions section the following:

Any<> should reflect powerful generalized generic features to be able to 
constrain types even further. (This should have its own proposal, which will 
extend Any<> proposed here.)

I hope my English wasn't too bad, please don’t blame me. :D

-- 
Adrian Zubarev
Sent with Airmail

Am 17. Mai 2016 bei 22:07:00, Austin Zheng (austinzh...@gmail.com) schrieb:


Austin

On Tue, May 17, 2016 at 1:02 PM, Matthew Johnson <matt...@anandabits.com> wrote:

On May 17, 2016, at 2:45 PM, Austin Zheng via swift-evolution 
<swift-evolution@swift.org> wrote:

Feel free to add as much of this proposal into yours as you want.

The trend is towards smaller proposals and introducing change in stages.  Since 
Adrian’s proposal is almost ready it’s probably best to move ahead with it 
as-is and follow up with generalized existentials (yours), and then possibly a 
third on “opening” existentials.


Austin

On Tue, May 17, 2016 at 12:09 PM, Adrian Zubarev via swift-evolution 
<swift-evolution@swift.org> wrote:
+1 for extending my proposal and making `Any<>` even more a powerful beast. :)

-- 
Adrian Zubarev
Sent with Airmail

Am 17. Mai 2016 bei 20:52:34, Austin Zheng via swift-evolution 
(swift-evolution@swift.org) schrieb:

I put together the skeleton of a proposal detailing enhancements to how 
associated types can be referenced in Swift 3+. It's certainly not ready for 
submission, but I think it gets across my ideas pretty well. Would love to 
gather feedback and especially improvements.

Be unsparing; whatever form this feature takes will profoundly affect how Swift 
developers program for years, so it needs to be done right.

See below:

Proposal

An existential type is defined using the "Any<...>" construct. Existential 
types can be nested.

The empty existential type "Any<>" is typealiased to 'Any'.

Within the angle brackets are zero or more 'clauses'. Clauses are separated by 
semicolons. (This is so commas can be used in where constraints, below. Better 
ideas are welcome. Maybe it's not necessary; we can use commas exclusively.)

There are five different possible clauses:

'class'. Must be the first clause, if present. Places a constraint on the 
existential to be any class type. (Implies: Only one can exist. Mutually 
exclusive with class name clause.)

(In the future a follow-up proposal should add in 'struct' or 'value' as a 
counterpart.)

Class name. Must be the first clause, if present. (Implies: Only one can exist. 
Mutually exclusive with 'class'.) Places a constraint on the existential (not 
really an existential anymore) to be an instance of the class, or one of its 
subclasses.
Example: Any<UIViewController; UITableViewDataSource; UITableViewDelegate>
"Any UIViewController or subclass which also satisfies the table view data 
source and delegate protocols"
Dynamic protocol. This is entirely composed of the name of a protocol which has 
no associated types or Self requirement.

Example: Any<CustomStringConvertible; BooleanType>
"Any type which conforms to both the CustomStringConvertible and BooleanType 
protocols"

I'm going to use 'static protocol' to refer to a protocol with associated types 
or self requirements. Feel free to propose a more sound name.

Self-contained static protocol, simple. This is composed of the name of a 
static protocol, optionally followed by a 'where' clause in which the 
associated types can be constrained (with any of the three basic conformance 
types: subclassing, protocol conformance, or type equality). Associated types 
are referred to with a leading dot.

Example: Any<Collection where .Generator.Element : NSObject, .Generator.Element 
: SomeProtocol>
"Any type that is a Collection, whose elements are NSObjects or their 
subclasses conforming to SomeProtocol."

Bound static protocol. This is the same as a self-contained static protocol, 
but with a leading "<name> as " which binds the protocol to a generic 
typealias. The name can be then be used in subsequent clauses to build 
constraints.

Example: Any<T as Collection; IntegerLiteralConvertible where 
.IntegerLiteralType == T.Element>.
"Any type that is a Collection, and also can be built from an integer literal, 
in which the collection elements are the same type as the type of the integer 
used for the integer literal conformance."

There will be rules to prevent recursive nesting. For example, if generic 
typealiases are allowed, they cannot refer to each other in a circular manner 
(like how structs can't contain themeselves, and you can't create a cyclic 
graph of enums containing themselves).

How an existential can be used depends on what guarantees are provided by the 
clauses. For example, 'Any<Equatable>' can't be used for much; if there were 
any methods on Equatable that did not use the associated types at all you'd be 
able to call them, but that's about it. However, 'Any<Equatable where .Self == 
String>' would allow for == to be called on instances. (This is a stupid 
example, since Any<Equatable where .Self == String> is equivalent to 'String', 
but there are almost certainly useful examples one could come up with.)

In order of increasing 'power':
Don't constrain any associated types. You can pass around Any<Equatable>s, but 
that's about it.
Constrain associated types to conform to protocols.
Fully constrain associated types.


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

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


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


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

Reply via email to