I absolutely share Matthew’s view of #Self (or whatever it ends up being called) and think this is really needed.
On the other hand I don’t think that a simple placeholder for the defining type is necessary as proposed by Vladimir, especially not if it is the third variant of something Self-like. -Thorsten > Am 12.05.2016 um 17:36 schrieb Matthew Johnson via swift-evolution > <[email protected]>: > >> >> On May 12, 2016, at 10:19 AM, Vladimir.S <[email protected] >> <mailto:[email protected]>> wrote: >> >> Inline >> >> On 11.05.2016 21:31, Matthew Johnson wrote: >>> >>> >>> Sent from my iPad >>> >>>> On May 11, 2016, at 11:43 AM, Vladimir.S <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>> Well, I believe I understand now what *you mean* under #Self. OK. >>>> Thank you for clarifications. In my terminology 'this' could be called >>>> BaseSelf. Your "thing" just can not be called #Self. IMO in initial >>>> proposal #Self means not more than placeholder for the concrete type >>>> name(inside type declaration or inside protocol). >>>> >>>> You propose just something different, more advanced than initial >>>> #Self, you propose not some static "thing" but extended behavior if >>>> #Self is a return type of protocol requirement. >>>> >>>> I strictly against to couple the initial proposal of #Self and your >>>> proposal for extended features (for protocol conformance of >>>> `->#Self`). Please be clear and obvious regarding the name of that >>>> feature. I really think the behavior you propose can not be called >>>> #Self(or Type) >>>> >>>> What I suggest: de-couple these proposals to: >>>> >>>> a) initial proposal of #Self as placeholder for concrete type name. >>>> Choose the name for it. Probably StaticSelf, or Type, or somehting >>>> else >>>> >>>> b) your proposal for BaseSelf feature. I'll definitely support it with >>>> just name changed to clearly reflect its propose. >>> >>> I don't believe the initial proposal stated how it would behave in a >>> protocol. However I do believe the feature I am talking about covers >>> all of the use cases Erica had in mind while also providing useful >>> semantics when used in a protocol requirement. Erica, please correct me >>> if I'm wrong. >> >> Well.. Yes, I also don't see statements regarding how `->#Self` would behave >> in a protocol in initial proposal. *This is why* I suggest to de-couple what >> *was* in initial proposall, and what you are suggesting as *addition* to the >> proposal. >> >> Again. I fully support the behavior you suggest, but I strongly feel like >> 'that' #Self can't be named #Self, as some derived(from conformed class) >> class X does not return 'self'. It return 'self or one of base classes'. >> Let's call it 'SelfOrBase' for now. >> >> What we have now: >> >> protocol A { >> func f1() -> Self >> func f2(s: Self) >> } >> >> struct S: A { >> func f1() -> S/*#Self*/ {return self} >> func f2(s: S/*#Self*/) {} >> } >> >> class C: A { >> func f1() -> Self /*only Self, can't write C here*/ {return self} >> func f2(s: C/*#Self*/) {} >> } >> >> final class FC: A { >> func f1() -> Self /*can write FC here, ==#Self*/ {return self} >> func f2(s: FC/*#Self*/) {} >> } >> >> I believe, for clarity, after we introduce #Self(or whatever name it will >> have) we need to require `#Self` in protocol as type of method parameter: >> >> protocol A { >> func f1() -> Self // this could be Self and could be #Self > > What in the original proposal makes you think Self and #Self would be > interchangeable here? Again, the proposal was for #Self to be invariant. > Self is covariant. Those are very different things. > > The semantics in the original proposal were unspecified with regards to > protocols. I am simply extending it to retain the invariant semantics that > the proposal *did* specified when it is used as a protocol requirement. > >> func f2(s: #Self) // this always will be #Self in implementation >> >> // this should not be allowed any more >> //func f2(s: Self) >> } >> >> struct S: A { >> // as you see we'd have `->#Self` in implementation >> func f1() -> #Self {return self} >> func f2(s: #Self) {} >> } >> >> class C: A { >> func f1() -> Self /*only Self, can't write C here*/ {return self} >> func f2(s: #Self) {} >> } >> >> final class FC: A { >> func f1() -> Self /*can write FC here, ==#Self*/ {return self} >> func f2(s: #Self) {} >> } >> >> The above is what *I think* was in initial proposal regarding #Self. >> >> About your suggestion. I just trying to understand it in details. >> Please point me where I understand your suggestion incorrectly. >> >> Do you think about such start points? : >> >> class Base { >> func f() -> Base {return Base()} >> } >> >> class Derived1: Base { >> override func f() -> Derived1 {return Derived1()} >> } >> >> class Derived2: Base { >> override func f() -> Derived2 {return Derived2()} >> } >> >> If so, do you want to introduce such a protocol: >> >> protocol A { >> func f() -> #Self >> } >> >> and then conforms Base class to it? : >> >> extension Base : A {} >> >> To be able to use : >> >> let a : A = Derived2() >> let some = a.f() // you expect some.dynamicType is Derived2 > > The protocol specifies #Self (or Type, which we are not calling it). It is > conformed to by Base. This means the return type of `f` is only guaranteed > to be Base. It *may* be Derived2, but it need not be. Obviously given this > example we know it is Derived2 because we can see the implementation but the > type system does not. This means `some` has type of Base. Its dynamicsType > *may* be Derived2 (and again in this case we can see that it will be) but > that is not guaranteed by the type system. > >> >> I understand correctly? >> >> At this point you say that all is OK and #Self works as expected, each class >> returns really #Self and protocol conformation applied. >> But I believe this is not true. We *can* have this: >> >> class Derived3: Base { >> // no override for f(). will be used from base class >> } >> >> Now. What does Derived3().f() returns? It returns instance of Base. >> Is #Self for Derived3 equals to `Base` ? No. >> Does Derived3 conforms to protocol `A` in this case? No. >> But it *must* conform as you think you can conform its base class. >> This is the problem I see. > > What you are missing is that #Self is not the same as Self. It is invariant. > A was originally conformed to by Base. The requirement is invariant and > becomes fixed by the conformance declaration. In this case it is fixed to > Base. > > You have not explained why you think #Self should be invariant when used in a > type context and covariant when used in a protocol context. This expectation > is what is confusing you. If you really what that semantic I think the > burden is on you to make the case that we need something with this mixed > semantic. I think it is much more confusing than having separate constructs > for covariant and invariant semantics. > >> >> This is why I think it must be something separate from #Self, like >> SelfOrBase - in this case, protocol will looks like: >> >> protocol A { >> func f() -> SelfOrBase >> } >> >> then you can conform Base to A, >> >> extension Base : A {} >> >> and Derived3 fully conforms to this protocol(it returns instance of base >> class), all is OK and all is consistent. >> >> If I'm wrong somewhere please point me with clarification. Thank you. > > Again, what you are calling SelfOrBase is *exactly* what I am calling Type > (or #Self). It has consistent invariant semantics in all contexts. > >> >>> >>> You want to make the semantics of #Self / Type be covariant when used in >>> a protocol requirement. This makes no sense to me as it is explicitly >>> *not* covariant when used within a class declaration. We already have a >>> covariant construct (Self) and the proposal is to introduce an invariant >>> construct (#Self or Type). The invariant semantic should be consistent >>> regardless of whether it is used in a protocol requirement or a type >>> declaration. >>> >>> IMO BaseSelf is a poor choice of name for something that is supposed to >>> be valid syntax in value types as well as classes. >>> >>>> >>>>> On 11.05.2016 18:58, Matthew Johnson wrote: 'f' would return E for >>>>> E, F and G. Because the conformance is declared by E the >>>>> requirement to return #Self is fixed as an invariant requirement to >>>>> return E for all potential subclasses. >>>>> >>>>>>> >>>>>>> Probably you(we) need another proposal, like BaseSelf (or >>>>>>> SuperSelf) that means "this class or any its base class", then I >>>>>>> understand how such a `f()->BaseSelf` protocol requirement can >>>>>>> be applied to E class and also be true for F&G classes (as f() >>>>>>> inherited from base class will return instance of E which is >>>>>>> base for both). >>>>> This is exactly what #Self (or Type) does. The behavior you have >>>>> been describing is the behavior of Self which already exists. > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
