on Thu Jun 09 2016, Douglas Gregor <dgregor-AT-apple.com> wrote: >> On Jun 8, 2016, at 11:57 AM, Dave Abrahams via swift-evolution > <[email protected]> wrote: >> >> >> on Sun Jun 05 2016, Douglas Gregor <[email protected] > <mailto:[email protected]>> wrote: >> > >>> Sent from my iPhone >>> >>>> On Jun 5, 2016, at 6:41 PM, Matthew Johnson <[email protected]> wrote: >>>> >>>> >>>> >>>> Sent from my iPad >>>> >>>>> On Jun 5, 2016, at 6:20 PM, Douglas Gregor <[email protected]> wrote: >>>>> >>>>> >>>>>> On May 18, 2016, at 12:35 AM, Austin Zheng <[email protected]> wrote: >>>>>> >>>>>> I've put together a considerably more detailed draft proposal, >>>>>> taking into account as much of Matthew's feedback as I could. You >>>>>> can find it below: >>>>>> >>>>>> https://github.com/austinzheng/swift-evolution/blob/az-existentials/proposals/XXXX-enhanced-existentials.md >>>>>> >>>>>> Since there is no chance this will come up for review anytime >>>>>> soon, I expect to make significant revisions to it over the next >>>>>> month or so. Any feedback would be greatly appreciated. >>>>> >>>>> This is very much Swift 4 territory, but I can’t help myself… so… >>>>> >>>>> The actual feature description is spread out through this very long >>>>> document, with user-facing ideas (e.g., using “anonymous associated >>>>> types”) intermixed with deeper technical details (existential type >>>>> equivalence), so it’s very daunting to read. Please bring the >>>>> user-facing features to the front (“Proposed Solution”) with >>>>> examples, and save the deeper technical details for “Detailed >>>>> Design”. You want more readers to make it through the part that >>>>> affects them. >>>>> >>>>> Shortcut 'dot' notation: If there is only one protocol with >>>>> associated types specified in the requirements, and there are no >>>>> nested Any<...> requirements with where clauses of their own, that >>>>> protocol's name can be omitted from the whereclause constraints: >>>>> >>>>> // Okay >>>>> // Would otherwise be Any< ~ where Collection.Element == Int> >>>>> let a : Any<class, Collection, Any<Streamable, CustomStringConvertible> >>>>> where .Element == Int> >>>>> >>>>> // NOT ALLOWED >>>>> // Both Collection and OptionSetType have associated types. >>>>> let b : Any<Collection, OptionSetType where .Element == Int> >>>>> FWIW, I think “.Element == Int” should be the only syntax. In >>>>> generic signatures, if you have two different protocols with >>>>> same-named associated types, and a given type parameter (or >>>>> associated type) conforms to both protocols, the associated types >>>>> are (implicitly) made equivalent via an inferred same-type >>>>> constraint. So there’s no reason to introduce the >>>>> “Collection.Element == Int” syntax, because the “Collection” part >>>>> is basically irrelevant. >>>>> >>>>> Once existentials have been suitably enhanced, there is a strong >>>>> analogy between an existential and a generic signature with a >>>>> single type parameter that you can’t name. An existential >>>>> Any<Collection where .Element : Equatable> has most of the same >>>>> characteristics as a generic something with the signature <T : >>>>> Collection where T.Element : Equatable>. Specifically, the sections >>>>> on “Existential type equivalence”, “Ordering”, “Real types to >>>>> anonymous associated types”, “Anonymous associated types to real >>>>> types”. could be reduced to a few small, simple examples and a >>>>> mention of the analogous behavior of generics. It will be far >>>>> easier to explain this way, and readers don’t need to get immersed >>>>> in the details. Where there are differences vs. generics, that’s >>>>> important to point out. >>>>> >>>>> “Associated typealias rewriting”: this also falls out of the equivalence >>>>> with generics + SE-0092. >>>>> >>>>> “Associated types and member exposure”: you don’t make the point >>>>> that it only makes sense to refer to the associated types of a let >>>>> constant; a var could change its type dynamically, which would >>>>> invalidate the typing rules. Did you consider just using >>>>> “x.dynamicType” in the type grammar for this? It’s more general, in >>>>> that you can refer to associated types but also talk about the >>>>> dynamic type of “x” itself, e.g., >>>>> >>>>> let x: Equatable = … >>>>> let y: Equatable = … >>>>> if let yAsX = y as? x.dynamicType { … x == yAsX … } >>>>> >>>>> which is (almost?) as powerful as a general “open” expression. >>>>> >>>>> I’m not a fan of the “anonymous associated types” terminology: >>>>> these are associated types of a type of some runtime-defined >>>>> value. The only thing “anonymous” about them is that it’s harder to >>>>> spell the base type; otherwise, they’re just like associated types >>>>> of a generic type parameter. Again, the generics analogy is strong >>>>> here. >>>>> >>>>> FWIW, I don’t think we’ll ever need “opening existentials” with >>>>> what you’ve described here. Also, remember that a method of a >>>>> protocol extension essentially opens “Self”, so we already have one >>>>> way to open an existential (and that’s probably enough). >>>>> >>>>> I was a little surprised you didn’t point out that AnyObject could become >>>>> >>>>> typealias AnyObject = Any<class> >>>>> >>>>> or give the nice “AnyCollection” syntax: >>>>> >>>>> typealias AnyCollection<T> = Any<Collection where .Element == T> >>>>> >>>>> the latter of which is fairly important, because it gives nice >>>>> syntactic sure to one of the most highly-requested features >>>>> [*]. I’d suggest having that example very, very early. >>>>> >>>>> - Doug >>>>> >>>>> [*] That generally comes in as “Swift should have parameterized >>>>> protocols…” >>>> >>>> Great feedback here Doug. >>>> >>>> FWIW, we also occasionally get "Swift should have parameterized >>>> protocols" in the context of multiple conformances by the same >>>> concrete type (as in things like ConvertibleTo<T> protocol). >>> >>> I know. From the bugs I've seen it's at least 10x as many requests for >>> "any collection of some element type" as for any actually reason why >>> one would need parameterize a protocols. >> >> That does, however, speak for the idea that a concise and obvious > syntax >> should be supported for that use-case. >> >> Personally, it doesn't seem ridiculous to me that some associated > types >> might usefully be written as type parameters on a protocol. As >> Collection shows, not all associated types are equally important. >> Approximately nobody wants the existential “Collection where Index > == >> Int.” > > I’ve toyed with some form of this idea before, and IIRC it was > discussed on this list at one point, where some or all associate types > move up to the “type parameter” position in the grammar, e.g., > > protocol Collection<Element> : Sequence<Element> { > associatedtype Index > associatedtype SubSequence > } > > However, unless that is semantically a type parameter in the sense > that one can have a single concrete type conform to Collection<A> and > Collection<B> separately, I think it’s misleading to go this route, > even if it does give us the clean “Collection<Int>” syntax.
Excellent point! I hadn't considered it. -- Dave _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
