> On Jan 29, 2017, at 10:47 PM, Slava Pestov <[email protected]> wrote: > > >> On Jan 29, 2017, at 2:05 PM, Matthew Johnson via swift-evolution >> <[email protected] <mailto:[email protected]>> wrote: >> >>> >>> On Jan 29, 2017, at 3:52 PM, Xiaodi Wu <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>> On Sun, Jan 29, 2017 at 3:35 PM, Matthew Johnson <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>>> On Jan 29, 2017, at 3:24 PM, Xiaodi Wu <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>> On Sun, Jan 29, 2017 at 3:11 PM, Matthew Johnson <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>>> On Jan 29, 2017, at 3:05 PM, Xiaodi Wu <[email protected] >>>>> <mailto:[email protected]>> wrote: >>>>> >>>>> On Sun, Jan 29, 2017 at 2:40 PM, Matthew Johnson <[email protected] >>>>> <mailto:[email protected]>> wrote: >>>>> >>>>>> On Jan 29, 2017, at 2:25 PM, Xiaodi Wu <[email protected] >>>>>> <mailto:[email protected]>> wrote: >>>>>> >>>>>> On Sun, Jan 29, 2017 at 2:16 PM, Matthew Johnson <[email protected] >>>>>> <mailto:[email protected]>> wrote: >>>>>> >>>>>>> On Jan 29, 2017, at 2:01 PM, Xiaodi Wu <[email protected] >>>>>>> <mailto:[email protected]>> wrote: >>>>>>> >>>>>>> On Sun, Jan 29, 2017 at 1:37 PM, Matthew Johnson >>>>>>> <[email protected] <mailto:[email protected]>> wrote: >>>>>>> >>>>>>> >>>>>>> Sent from my iPad >>>>>>> >>>>>>> On Jan 29, 2017, at 12:58 PM, Xiaodi Wu via swift-evolution >>>>>>> <[email protected] <mailto:[email protected]>> wrote: >>>>>>> >>>>>>>> Cool. Another avenue of improvement here is relaxing the single-class >>>>>>>> spelling rule for the sake of composing typealiases. >>>>>>>> >>>>>>>> As Matthew mentioned, if I have class Base and typealiases Foo = Base >>>>>>>> & Protocol1 and Bar = Base & Protocol2, it'd be nice to allow Foo & >>>>>>>> Bar. >>>>>>>> >>>>>>>> It'd be nice to go one step further: given class Derived : Base, if I >>>>>>>> have typealiases Foo2 = Base & Protocol1 and Bar2 = Derived & >>>>>>>> Protocol2, then it could be permitted to write Foo2 & Bar2, since >>>>>>>> there is effectively only one subclass requirement (Derived). >>>>>>>> >>>>>>>> As I understand it, the rationale for allowing only one subclass >>>>>>>> requirement is that Swift supports only single inheritance. Thus, two >>>>>>>> disparate subclass requirements Base1 & Base2 would make your >>>>>>>> existential type essentially equivalent to Never. But Base1 & Base1 & >>>>>>>> Base1 is fine for the type system, the implementation burden (though >>>>>>>> greater) shouldn't be too awful, and you would measurably improve >>>>>>>> composition of typealiases. >>>>>>> >>>>>>> Yes, this is what I was indicating in my post as well. >>>>>>> >>>>>>> Are you suggesting that Base1 & Base2 compose to a type that is treated >>>>>>> identically to Never do you think it should be an immediate compiler >>>>>>> error? I remember having some discussion about this last year and >>>>>>> think somebody came up with a very interesting example of where the >>>>>>> former might be useful. >>>>>>> >>>>>>> Last year's discussion totally eludes me for some reason. But sure, if >>>>>>> deferring the error until runtime is actually useful then why not? In >>>>>>> the absence of an interesting use case, though, I think it'd be nice >>>>>>> for the compiler to warn you that Base1 & Base2 is not going to be what >>>>>>> you want. >>>>>> >>>>>> Deferring to runtime isn’t what I mean. If you try to actually *do* >>>>>> anything that requires an instance of `Base1 & Based` (which you almost >>>>>> always would) you would still get a compile time error. >>>>>> >>>>>> I managed to dig up the example from last year’s thread and it is >>>>>> definitely a good one: >>>>>> >>>>>> func intersection<T, U>(ts; Set<T>, us: Set<U>) -> Set<T & U> >>>>>> >>>>>> The desire is that we are always able to produce a result set. When T & >>>>>> U is uninhabitable it will simply be an empty set just like Set<Never> >>>>>> has a single value which is the empty set. >>>>>> >>>>>> Currently, Set<Never> is impossible because Never is not Hashable :) >>>>> >>>>> Ahh, good point. I hadn’t tried it. It can easily be made Hashable with >>>>> a simple extension though - this code compiles today: >>>>> >>>>> extension Never: Hashable { >>>>> public var hashValue: Int { return 0 } >>>>> } >>>>> public func ==(lhs: Never, rhs: Never) -> Bool { return false } >>>>> let s = Set<Never>() >>>>> >>>>>> Since concrete types *can't* be used, this example seems like it'd be of >>>>>> little use currently. How widely useful would it be to have an >>>>>> intersection facility such as this when T != U even if that restriction >>>>>> were lifted, though? Seems like the only real useful thing you can do >>>>>> with generic Set<T & U> is based on the fact that it'd be Set<Hashable>. >>>>>> Other than those immediate thoughts, I'll have to think harder on this. >>>>> >>>>> Sure, it’s possible that this is the only interesting example and may not >>>>> have enough value to be worthwhile. But I found it interesting enough >>>>> that it stuck around in the back of my mind for 8 months! :) >>>>> >>>>> Hmm, it had not occurred to me: instantiating a Set<Hashable> is not >>>>> supported (and you can substitute for Hashable any protocol you want). >>>>> Thus, for any Set<T> and Set<U> that you can actually instantiate, unless >>>>> T and U are both classes and one inherits from the other (in which case >>>>> the generic `intersection<X>(a: Set<X>, b: Set<X>) -> Set<X>` already >>>>> suffices), Set<T & U> must be the empty set. This is not a very >>>>> interesting result. >>>> >>>> Yes, but this is a limitation due to the fact the existentials for a >>>> protocol do not conform to the protocol. In some cases the existential >>>> *cannot* conform to the protocol but in many cases (especially common >>>> cases) it *can*. It just doesn’t today. There is widespread desire to >>>> see this situation improve. >>>> >>>> Sure, but when will be the day that existentials conform to their own >>>> protocol when they can do so, *and* we extend `&` to value types (probably >>>> not until they can express some sort of meaningful subtyping relationship >>>> to each other)? >>> >>> I hope it isn’t *too* long before existentials conform to their own >>> protocol at least in simple cases - Swift 5 if it doesn’t make it into >>> Swift 4. >>> >>> I will bet you two virtual alcoholic beverages that it won't happen before >>> Swift 7 or one that it won't happen before Swift 9. >>> >>> I am suggesting this proposal be generalized such that it discusses >>> concrete subtype / supertype relationships rather than restricting it’s >>> scope to classes. If that approach is adopted then `&` would allow value >>> types as soon as this proposal is implemented. >>> >>> It seems arbitrary and unnecessary to restrict it to classes even if that >>> is where it would be most useful when it is first implemented. >>> >>> One can naturally relax the rules in tandem with the design and >>> implementation of prerequisite features that make the more relaxed rules >>> useful. The point I'm trying to make is: there is currently no value of X >>> for which the following statement holds true-- >>> >>> "If only it weren't for the restriction against writing `Base1 & Base2`, >>> I'd be able to implement the interesting algorithm X." >>> >>> So it seems reasonable to error on `Base1 & Base2`. >> >> If you’re right about the timeline for existentials conforming to their >> protocols I would agree with you wholeheartedly. I’m not sure why we have >> such different perspectives on when that might happen. It has certainly >> received plenty of demand from the community and caused some degree of >> confusion, usually in relatively simple cases (since we only have relatively >> simple existentials today). > > Here are a couple of e-mails I sent recently explaining why self-conforming > existentials are tricky. Someone with a deep understanding of the compiler > needs to put some thought into how an implementation could work… > > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160815/026349.html > > <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160815/026349.html> > https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20161226/004292.html > > <https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20161226/004292.html> Thanks for the links, I hadn’t seen these previously. For some reason I thought the implementation complexity was focused on protocols with Self and associated type requirements and so basic support might be easier to implement as a first step.
> >> >>> >>>> >>>> At that point, I'd advocate for using compiler magic to make uninhabited >>>> types like Never a subtype of all types conforming to all protocols. Then, >>>> we could actually write Set<Never> without having to implement conformance >>>> to Hashable by writing a bogus `==` function. And we could replace >>>> EmptyCollection with Collection<Never> and simplify the standard library >>>> API surface that way (since Array<Never>() would then be a value of type >>>> Array<T>, etc.). And, your demonstrated use case would become interesting. >>>> Since there is a pretty good chance that you and I won't be alive by then, >>>> I'm happy to punt on the ideation process for this :) >>>> >>>>> >>>>> It generalizes easily to any cases where you have a generic type that is >>>>> useful despite not necessarily having access to instances of the >>>>> parameterized type. >>>>> >>>>> If we allow this, I *think* all uninhabitable types could be unified >>>>> semantically by making `Never` a protocol and giving them implicit >>>>> conformance. >>>>> >>>>>> >>>>>> This example points even more strongly in the direction of allowing >>>>>> *any* concrete type to be used, not just classes - even today we could >>>>>> produce uninhabitable existentials like this using value types. >>>>>> >>>>>> Here’s the link to the thread: >>>>>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160523/019463.html >>>>>> >>>>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160523/019463.html> >>>>>>> >>>>>>> >>>>>>>> On Sun, Jan 29, 2017 at 12:41 Austin Zheng <[email protected] >>>>>>>> <mailto:[email protected]>> wrote: >>>>>>>> The "class comes first" requirement made more sense when the proposed >>>>>>>> syntax was still "Any<T, U, V>", intentionally mirroring how the >>>>>>>> superclass and conformances are declared on a class declaration (the >>>>>>>> archives contain more detailed arguments, both pro and con). Now that >>>>>>>> the syntax is "T & U & V", I agree that privileging the class >>>>>>>> requirement is counterintuitive and probably unhelpful. >>>>>>>> >>>>>>>> Austin >>>>>>>> >>>>>>>> > On Jan 29, 2017, at 10:37 AM, Matt Whiteside via swift-evolution >>>>>>>> > <[email protected] <mailto:[email protected]>> wrote: >>>>>>>> > >>>>>>>> > Thanks for writing this proposal David. >>>>>>>> > >>>>>>>> >> On Jan 29, 2017, at 10:13, Xiaodi Wu via swift-evolution >>>>>>>> >> <[email protected] <mailto:[email protected]>> >>>>>>>> >> wrote: >>>>>>>> >> >>>>>>>> >> As Matthew mentioned, the rules can certainly later be relaxed, but >>>>>>>> >> given that this proposal has the compiler generating fix-its for >>>>>>>> >> subclasses in second position, is there a reason other than >>>>>>>> >> stylistic for demanding MyClass & MyProtocol instead of MyProtocol >>>>>>>> >> & MyClass? >>>>>>>> >> >>>>>>>> >> From a naive perspective, it seems that if the compiler understands >>>>>>>> >> my meaning perfectly, it should just accept that spelling rather >>>>>>>> >> than complain. >>>>>>>> > >>>>>>>> > I had that thought too. Since ‘and’ is a symmetric operation, >>>>>>>> > requiring the class to be in the first position seems >>>>>>>> > counter-intuitive. >>>>>>>> > >>>>>>>> > -Matt >>>>>>>> > >>>>>>>> > _______________________________________________ >>>>>>>> > swift-evolution mailing list >>>>>>>> > [email protected] <mailto:[email protected]> >>>>>>>> > https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>>> > <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>>>>> >>>>>>>> _______________________________________________ >>>>>>>> swift-evolution mailing list >>>>>>>> [email protected] <mailto:[email protected]> >>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>> >>> >>> >> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] <mailto:[email protected]> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
