On Sun, Jun 11, 2017 at 12:43 PM, Gor Gyolchanyan <[email protected]> wrote:
> I have no better name besides a factory initializer for now. > I have thought about this some more and came to this conclusion about the > keyword: > Let the keyword be universally applied to all factory initializers, to > statically enforce the rules of factory initializers (see below), because > the more I think of it, the more I realize that you'd generally not want to > mix factory and non-factory initializers, due to their vastly differing > purposes. > > Having said that, my current understanding of this proposal is as follows: > > * Allow marking initializers inside protocol extensions, class > declarations and class extensions as `factory`. > * In initializers marked as `factory`: > * Change the implicit `self` parameter to mean `the dynamic type of the > enclosing type` (just like it does in static methods). > * Disallow delegating initialization to initializers not marked as > `factory`. > * Require terminating the initializer by either returning a compatible > type (a conforming type for protocols, a derived instance for classes) or > returning `nil` (if the initializer is failable). > * In initializers inside enum declarations, enum extensions, struct > declarations and struct extensions: > * Allow terminating the initializer by returning an instance of the type > being initialized. > Sounds reasonable to me. On Jun 11, 2017, at 7:38 PM, Xiaodi Wu <[email protected]> wrote: > > On Sun, Jun 11, 2017 at 10:34 AM, Gor Gyolchanyan <[email protected]> > wrote: > >> I just didn't want to use the commonly proposed `factory` word, because >> it implies a specific semantic tied to the factory method pattern. >> I gave it another thought and I'm thinking maybe we can forego the >> annotation and have the compiler deduce it automatically. >> There are only two places where an indirect initializer can exist: >> * Protocol extensions, returning a conforming type. >> * Classes, returning an instance. >> It doesn't make sense to have this on value types, since they do not have >> subtypes of any kind. >> Indirect initializers are very unambiguous in protocol extensions, >> because the only other way of implementing an initializer in a protocol >> extension is via delegating initialization, so the indirect-ness of the >> initializer can be statically determined by whether or not there is a >> delegating initializer involved. >> If the initializer in a protocol extension has a delegating >> initialization on any execution path, then returning an instance is >> disallowed and vice versa. This will ensure strict separation of >> initializer types for the compiler to generate code for. >> If a failable initializer in a protocol extension unconditionally returns >> `nil`, then no initialization takes place anyway, so it doesn't matter, >> which one the compiler chooses. >> In classes this is a bit difficult, because besides delegating >> initializers, they also can initialize the members directly. >> So, in addition to the distinguishing rule for the protocol extensions, >> classes will also check whether any member is assigned to on any execution >> path. >> >> What do you think? >> > > Keywords aren't just for the compiler; they're for the human reader too! > If you believe the use of your proposed feature in protocol extensions is > unambiguous to humans as well as compilers, then IMO it makes sense not to > require another keyword in that place. I haven't thought deeply about > whether that would be the case. > > Clearly, you're saying that this is a more complicated situation with > classes; I think it makes sense for you to consider requiring a keyword > there. There is precedent for keywords modifying `init` to be required for > classes but not for value types (e.g., `convenience`). > > Regardless of whether a keyword is required or not, your feature needs a > name. And here again, I think it is puzzling that you are calling them > "indirect initializers" when there is already another meaning for > "indirect" in Swift. Distinct concepts should have distinct names. > > On Jun 11, 2017, at 5:53 PM, Xiaodi Wu <[email protected]> wrote: >> >> On Sun, Jun 11, 2017 at 8:49 AM, Gor Gyolchanyan <[email protected]> >> wrote: >> >>> Can you recall the reasons why the removal of access modifiers on >>> extensions was rejected? >>> >> >> It was an unassailable reason, really: people found this shorthand useful >> and wanted to continue to use it--it is the only way to specify that >> multiple members are public without explicitly labeling each one. The core >> team agreed it was useful. >> >> My takeaway from the whole episode (I was greatly in favor of removing >> this shorthand, as it's highly inconsistent with all other access modifier >> rules) is that in general, since the bar for new syntax is so high, if a >> shorthand made it into the language (and especially if it's kind of an >> inconsistent shorthand) the general presumption must be that it is highly >> desired. >> >> Also, do you think `indirect init` is confusing inside an `indirect enum`? >>> >> >> I do. These are unrelated definitions of "indirect," and I'm puzzled why >> you'd actively choose to run into issues with the same word meaning two >> things when you could choose another word. >> >> On Jun 11, 2017, at 4:40 PM, Xiaodi Wu <[email protected]> wrote: >>> >>> Removal of access modifiers on extensions has been proposed, reviewed, >>> and rejected, so that’s that. >>> >>> In general, Swift uses distinct keywords for distinct concepts, unlike >>> Rust which likes to reuse keywords in clever ways; if you’re finding that >>> things are getting confusing with one word meaning two things, that >>> shouldn’t be an invitation to rip out existing syntax but is probably a >>> good sign you shouldn’t be repurposing that keyword. >>> >>> >>> On Sun, Jun 11, 2017 at 03:28 Adrian Zubarev via swift-evolution < >>> [email protected]> wrote: >>> >>>> Yeah, well I messed up my proposal from last year about removing the >>>> access modifier on extensions and wish now I wasn’t that confused back than >>>> and made it right. >>>> >>>> The indirect keyword is literally the same story. The docs only says >>>> that this is only a shortcut. >>>> >>>> „To enable indirection for all the cases of an enumeration, mark the >>>> entire enumeration with the indirect modifier—this is convenient when the >>>> enumeration contains many cases that would each need to be marked with the >>>> indirect modifier.“ >>>> >>>> If you really wish to reuse that keyword here we might need to remove >>>> such shortcuts from the language (indirect enum, access modifier on >>>> extensions, anything else?). >>>> >>>> >>>> >>>> -- >>>> Adrian Zubarev >>>> Sent with Airmail >>>> >>>> Am 11. Juni 2017 um 10:12:38, Gor Gyolchanyan ([email protected]) >>>> schrieb: >>>> >>>> I always wondered, why is `indirect` allowed on the `enum` itself? >>>> Wouldn't it make more sense to apply it to individual cases that >>>> recursively refer to the `enum`? >>>> This question also applies to access modifiers on extensions. So, what >>>> is it supposed to do? Change the default access modifier from `internal` to >>>> whatever I specify? That's just confusing, reduces readability and the >>>> syntactic gain is marginal at best. >>>> If the `indirect` confusion becomes real, I'd suggest getting rid of >>>> `indirect enum` and using `indirect case` instead. >>>> >>>> On Jun 11, 2017, at 11:05 AM, Adrian Zubarev via swift-evolution < >>>> [email protected]> wrote: >>>> >>>> The proposal is looking good to me. :) It will also enable easy support >>>> for custom views using XIBs in iOS development without unnecessary view >>>> nesting. >>>> >>>> For instance the function from this example https://stackoverflow. >>>> com/a/43123783/4572536 could be used directly inside an init: >>>> >>>> class MyView : UIView { >>>> >>>> indirect init() { >>>> return MyView.instantiateFromXib() >>>> // Or after SR-0068 >>>> return Self.instantiateFromXib() >>>> } >>>> } >>>> >>>> There is still one little thing that bothers me, it might be a little >>>> bit confusing to have two different meanings of indirect on enums. >>>> >>>> indirect enum ArithmeticExpression { >>>> case number(Int) >>>> case addition(ArithmeticExpression, ArithmeticExpression) >>>> case multiplication(ArithmeticExpression, ArithmeticExpression) >>>> >>>> // This might makes no sense, but it would still be possible after >>>> // this proposal. >>>> indirect init(other: ArithmeticExpression) { >>>> return other >>>> } >>>> >>>> // Furthermore if the keyboard is applied to the enum >>>> // directly all other `indirect` uses are inferred. >>>> // Will this be implicitly `indirect` because of the previous fact? >>>> init() { … } >>>> } >>>> >>>> >>>> >>>> >>>> -- >>>> Adrian Zubarev >>>> Sent with Airmail >>>> >>>> Am 11. Juni 2017 um 00:38:56, Riley Testut via swift-evolution ( >>>> [email protected]) schrieb: >>>> >>>> Awesome! Updated my proposal to include what I believed to be the >>>> relevant portions of your indirect initializer idea. Let me know if there’s >>>> anything I missed or should change :-) >>>> >>>> https://github.com/rileytestut/swift-evolution/blob/master/p >>>> roposals/NNNN-factory-initializers.md >>>> >>>> On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <[email protected]> >>>> wrote: >>>> >>>> Hi, Riley! >>>> >>>> I think that's a great idea! We can merge the second part of my >>>> proposal (the `indirect init`) into your one and refine and consolidate the >>>> prerequisite proposal (about returning from `init` and possibly in-place >>>> member initializers) and bunch them up into a proposal cluster (the way >>>> swift coders did). >>>> Feel free to tear out any chunks from my proposal, while I think about >>>> a more in-depth rationale about revamping initialization syntax. 🙂 >>>> >>>> On Jun 10, 2017, at 8:36 PM, Riley Testut <[email protected]> >>>> wrote: >>>> >>>> Hi Gor 👋 >>>> >>>> I’m very much in fan of a unified initialization syntax. I submitted my >>>> own proposal for factory initializers a while back, but since it wasn’t a >>>> focus of Swift 3 or 4 I haven’t followed up on it recently. In the time >>>> since last working on it, I came to my own conclusion that rather than >>>> focusing on factory initialization, the overall initialization process >>>> should be simplified, which I’m glad to see someone else has realized as >>>> well :-) >>>> >>>> Here’s my proposal for reference: https://github.com/ >>>> apple/swift-evolution/pull/247/commits/58b5a93b322aae998eb40 >>>> 574dee15fe54323de2e Originally I used the “factory” keyword, but I >>>> think your “indirect” keyword may be a better fit (since it has precedent >>>> in the language and is not limited to “just” being about factory >>>> initialization). To divide your proposal up into smaller pieces for review, >>>> maybe we could update my proposal to use your indirect keyword, and then >>>> start a separate topic/proposal for the remaining aspects of your proposal? >>>> I agree that splitting it into smaller chunks may be better for the >>>> process. >>>> >>>> Let me know what you think! >>>> >>>> Riley >>>> >>>> >>>> On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution < >>>> [email protected]> wrote: >>>> >>>> >>>> This is a very interesting read. >>>> >>>> Thanks you! I tried to make it as clear and detailed as possible. 🙂 >>>> >>>> >>>> We did not discuss the 'indirect' idea at all on this list. Did you >>>> come up with it just now? In any case, my suggestion as to moving forward >>>> would be this: >>>> >>>> I was writing the proposal and was just about to write `factory init`, >>>> when it occurred to me: enums already have a keyword that does something >>>> very similar. It seemed to me that an initializer that doesn't initialize >>>> the instance in-place, but returns a completely separate instance from >>>> somewhere else, is kinda "indirectly" initializing the instance. Plus, the >>>> already established keyword and its semantic would reduce the learning >>>> curve for this new feature and separate it from a single specific use case >>>> (the "factory method" pattern). >>>> >>>> >>>> - Do you feel that both halves of your draft (expanding `return` in >>>> initializers, and `indirect` initializers) should absolutely be one >>>> proposal, or can they be separated? >>>> >>>> I think the `return` can be easily implemented first, while opening up >>>> an opportunity to later implement `indirect init`. The reason why I unified >>>> them was that the `return` idea on its own has very limited merit and could >>>> the thought of as a low-priority cosmetic enhancement. I wouldn't want it >>>> to be viewed that way because the primary purpose of that idea is to enable >>>> `indirect init` (which Cocoa and Cocoa Touch developers would be very happy >>>> about). >>>> >>>> >>>> a) If they can be separated because each half has individual merit, >>>> then these ideas may be more likely to succeed as separate proposals, as >>>> each can be critiqued fully and judged independently as digestible units. >>>> >>>> >>>> Very good point. The challenge is to correctly separate them, without >>>> losing context in their respective proposals and without bleeding the >>>> proposals into each other. >>>> >>>> >>>> >>>> b) If you intend to tackle all your ideas all at once, that's going to >>>> be a much bigger change--in terms of review effort, likely bikeshedding, >>>> and implementation effort. It'll probably be best to solicit initial >>>> feedback on this list first about `indirect` initializers, even if just to >>>> familiarize the community with the idea, before launching into a pitch of >>>> the whole proposal. >>>> >>>> I'd never send a pull request to swift-evolution without thoroughly >>>> discussing it here. I just though, if I'm going to write a whole proposal >>>> with examples and motivation, it would be easier to demonstrate it and >>>> discuss in with the community If I just went ahead and wrote the whole >>>> thing and sent the link. This way it would be clearer to the reader and the >>>> discussed changes would be accurately reflected by the commits I'd make to >>>> my proposal. >>>> >>>> Original Message >>>> >>>> On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution < >>>> [email protected]> wrote: >>>> >>>> On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <[email protected]> >>>> wrote: >>>> >>>>> Forked swift-evolution, created a draft proposal: >>>>> >>>>> https://github.com/technogen-gg/swift-evolution/blob/master/ >>>>> proposals/NNNN-uniform-initialization.md >>>>> >>>>> This is my first proposal, so I might have missed something or >>>>> composed it wrong, so please feel free to comment, fork and send pull >>>>> requests. 🙂 >>>>> >>>>> >>>> This is a very interesting read. We did not discuss the 'indirect' idea >>>> at all on this list. Did you come up with it just now? In any case, my >>>> suggestion as to moving forward would be this: >>>> >>>> - Do you feel that both halves of your draft (expanding `return` in >>>> initializers, and `indirect` initializers) should absolutely be one >>>> proposal, or can they be separated? >>>> >>>> a) If they can be separated because each half has individual merit, >>>> then these ideas may be more likely to succeed as separate proposals, as >>>> each can be critiqued fully and judged independently as digestible units. >>>> >>>> b) If you intend to tackle all your ideas all at once, that's going to >>>> be a much bigger change--in terms of review effort, likely bikeshedding, >>>> and implementation effort. It'll probably be best to solicit initial >>>> feedback on this list first about `indirect` initializers, even if just to >>>> familiarize the community with the idea, before launching into a pitch of >>>> the whole proposal. >>>> >>>> >>>> On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <[email protected]> wrote: >>>>> >>>>> Cool. I have reservations about idea #3, but we can tackle that >>>>> another day. (Real life things beckon.) But suffice it to say that I now >>>>> really, really like your idea #2. >>>>> On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <[email protected]> >>>>> wrote: >>>>> >>>>>> You know, come to think of it, I totally agree, and here's why: >>>>>> A normal initializer (if #2 is accepted) would *conceptually* have >>>>>> the signature: >>>>>> >>>>>> mutating func `init`(...) -> Self >>>>>> >>>>>> Which would mean that both `self` and the returned result are >>>>>> non-optional. >>>>>> A failable initializer could then have the signature: >>>>>> >>>>>> mutating func `init`() -> Self? >>>>>> >>>>>> Which would make the returned result optional, but leave `self` >>>>>> non-optional. >>>>>> This would make `return nil` less out-of-place, like you said, while >>>>>> still leaving `self` as a set-exactly-once `inout Self`. >>>>>> A factory initializer would then have the signature: >>>>>> >>>>>> static func `init`(...) -> Self >>>>>> >>>>>> or in case of a failable factory initializer: >>>>>> >>>>>> static func `init`(...) -> Self? >>>>>> >>>>>> Which would still make sense with the now legal `return ...` syntax, >>>>>> while adding the restriction of not having any `self` at all. >>>>>> So, annotating the initializer with the keyword `factory` would cause >>>>>> it to change the signature as well as remove any compiler assumptions >>>>>> about >>>>>> the dynamic type of the returned instance. >>>>>> >>>>>> In addition, idea #3 would be available for more deterministic >>>>>> in-place initialization. >>>>>> >>>>>> On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <[email protected]> wrote: >>>>>> >>>>>> On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <[email protected]> >>>>>> wrote: >>>>>> >>>>>>> So far, we've discussed two ways of interpreting `self = nil`, both >>>>>>> of which have a sensible solution, in my opinion: >>>>>>> >>>>>>> 1. It's a special rule like you said, which can be seen as >>>>>>> counter-intuitive, but recall that `return nil` is just as much of a >>>>>>> special rule and is also largely counter-intuitive. >>>>>>> >>>>>> >>>>>> `return nil` is “special,” but it doesn’t conflict with any other >>>>>> syntax because the initializer notionally has no return value. >>>>>> Personally, >>>>>> I have always disliked `return nil` in failable initializers for that >>>>>> reason, but I couldn’t come up with a better alternative. >>>>>> >>>>>> Your proposed idea to allow returning any value is interesting >>>>>> because, in the case of a failable initializer, `return nil` continues to >>>>>> have the same meaning if we consider the return value of the initializer >>>>>> to >>>>>> be of type `Self?`. For that reason, I think your idea #2 is quite >>>>>> clever, >>>>>> and it would go a long way in making `return nil` a lot less odd. It also >>>>>> increases the expressivity of initializers because it allows one to set >>>>>> the >>>>>> value of self and also return in one statement, clearly demonstrating the >>>>>> intention that no other code in the initializer should be run before >>>>>> returning. >>>>>> >>>>>> For all of those reasons, I think idea #2 is a winning idea. >>>>>> >>>>>> The benefit of `self = nil` is that it's much more in line with >>>>>>> initialization semantics, it provides more uniform syntax and it's a bit >>>>>>> less restrictive. >>>>>>> >>>>>>> 2. It's an `inout Self!`, like Greg said, which can be seen as more >>>>>>> cumbersome. Implicitly unwrapped optionals are a bit difficult, but this >>>>>>> "variation" of it is much more restrictive then the normal ones, because >>>>>>> unlike normal implicitly unwrapped optionals, this one cannot be >>>>>>> accessed >>>>>>> after being assigned nil (and it also cannot be indirectly assigned >>>>>>> `nil`, >>>>>>> because escaping `self` is not allowed before full initialization), so >>>>>>> there is only one possible place it can be set to nil and that's >>>>>>> directly >>>>>>> in the initializer. This means that `self` can be safely treated as >>>>>>> `inout >>>>>>> Self` before being set to nil (and after being set to nil, it doesn't >>>>>>> matter any more because you aren't allowed to access it, due to not >>>>>>> being >>>>>>> fully initialized). >>>>>>> >>>>>> >>>>>> I have to say, I don’t like either of these explanations at all. I >>>>>> think having a “special” IUO is a difficult sell; it is just conceptually >>>>>> too complicated, and I don’t agree that it gains you much. >>>>>> >>>>>> By your own admission, `self = nil` is wonky, and making the language >>>>>> wonkier because it currently has a parallel wonky feature in `return nil` >>>>>> seems like the wrong way to go. In addition, there’s nothing gained here >>>>>> that cannot be done with a defer statement; of course, defer statements >>>>>> might not be very elegant, but it would certainly be less wonky than >>>>>> inventing a new variation on an IUO to allow assignment of nil to self... >>>>>> For those reasons, I conclude that I’m not excited about your idea #1. >>>>>> >>>>>> Overall, I'd go with #2 because it involves much less confusing magic >>>>>>> and the restrictions of `self as inout Self!` are imposed by already >>>>>>> existing and well-understood initialization logic, so the provided >>>>>>> guarantees don't really come at the cost of much clarity. >>>>>>> >>>>>>> On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <[email protected]> wrote: >>>>>>> >>>>>>> >>>>>>> On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <[email protected]> >>>>>>> wrote: >>>>>>> >>>>>>>> I think a good approach would be to have `self = nil` only mean >>>>>>>> `the initializer is going to fail` because if your type is >>>>>>>> ExpressibleByNilLiteral, it means that the `nil` of your type already >>>>>>>> carries the same meaning as if your type was not >>>>>>>> ExpressibleByNilLiteral >>>>>>>> and was an optional instead, so having a failable initializer doesn't >>>>>>>> really make sense in that case (since you could've initialized `self` >>>>>>>> to >>>>>>>> its own `nil` in case of failure). Still, some valid use cases may >>>>>>>> exist, >>>>>>>> so the natural (and quite intuitive) way to circumvent this would be to >>>>>>>> call `self.init(nilLiteral: ())` directly. >>>>>>>> >>>>>>> >>>>>>> So you would create a special rule that `self = nil` means a >>>>>>> different thing in an initializer than it does in a function? >>>>>>> Essentially, >>>>>>> then, you’re creating your own variation on an implicitly unwrapped >>>>>>> optional, where `self` is of type `inout Self?` for assignment in >>>>>>> initializers only but not for any other purpose. Implicitly unwrapped >>>>>>> optionals are hard to reason about, and having a variation on it would >>>>>>> be >>>>>>> even harder to understand. I don’t think this is a workable design. >>>>>>> >>>>>>> It might be possible to have `self` be of type `inout Self?`; >>>>>>> however, I do think Greg is right that it would create more boilerplate >>>>>>> than the current situation. >>>>>>> >>>>>>> On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <[email protected]> wrote: >>>>>>>> >>>>>>>> >>>>>>>> On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <[email protected]> >>>>>>>> wrote: >>>>>>>> >>>>>>>>> The type of `self` could remain `inout Self` inside the failable >>>>>>>>> initializer. The ability to assign nil would be a compiler magic >>>>>>>>> (much like >>>>>>>>> `return nil` is compiler magic) that is meant to introduce uniformity >>>>>>>>> to >>>>>>>>> the initialization logic. >>>>>>>>> >>>>>>>>> The idea is to define all different ways initialization can take >>>>>>>>> place and expand them to be used uniformly on both `self` and all its >>>>>>>>> members, as well as remove the ways that do not make sense for their >>>>>>>>> purpose. >>>>>>>>> >>>>>>>>> Currently, there are 3 ways of initializing self as a whole: >>>>>>>>> 1. delegating initializer >>>>>>>>> 2. assigning to self >>>>>>>>> 3. returning nil >>>>>>>>> >>>>>>>>> #1: The delegating initializer is pretty much perfect at this >>>>>>>>> point, in my opinion, so no changes there. >>>>>>>>> >>>>>>>>> #2: The only exception in assigning to self is the `nil` inside >>>>>>>>> failable initializers. >>>>>>>>> >>>>>>>>> #3: The only thing that can be returned from an initializer is >>>>>>>>> `nil`, which is compiler magic, so we can thing of it as a misnomer >>>>>>>>> (because we aren't really **returning** anything). >>>>>>>>> >>>>>>>>> If, for a second, we forget about potential factory initializers, >>>>>>>>> returning anything from an initializer doesn't make much sense, >>>>>>>>> because an >>>>>>>>> initializer is conceptually meant to bring an existing object in >>>>>>>>> memory to >>>>>>>>> a type-specific valid state. This semantic was very explicitly in >>>>>>>>> Objective-C with `[[MyType alloc] init]`. Especially since even >>>>>>>>> syntactically, the initializer does not specify any return type, the >>>>>>>>> idea >>>>>>>>> of returning from an initializer is counter-intuitive both >>>>>>>>> syntactically >>>>>>>>> and semantically. >>>>>>>>> >>>>>>>>> The actual *behavior* of `return nil` is very sensible, so the >>>>>>>>> behavior, I imagine `self = nil`, would largely mean the same (except >>>>>>>>> not >>>>>>>>> needed to return immediately and allowing non-self-accessing code to >>>>>>>>> be >>>>>>>>> executed before return). Being able to assign `nil` to a non-optional >>>>>>>>> (ExpressibleByNilLiteral doesn't count) may feel a bit wonky, >>>>>>>>> >>>>>>>> >>>>>>>> What happens when Self is ExpressibleByNilLiteral and you want to >>>>>>>> initialize self to nil? That is what `self = nil` means if `self` is of >>>>>>>> type `inout Self`. If `self` is of type `inout Self` and Self is not >>>>>>>> ExpressibleByNilLiteral, then it must be an error to assign nil to >>>>>>>> self. >>>>>>>> Anything else does not make sense, unless `self` is of type `inout >>>>>>>> Self?`. >>>>>>>> >>>>>>>> but not as wonky as returning nil from something that is meant to >>>>>>>>> initialize an object in-place and doesn't look like it should return >>>>>>>>> anything. >>>>>>>>> >>>>>>>>> # Factory Initializers >>>>>>>>> >>>>>>>>> In case of factory initializers, the much discussed `factory init` >>>>>>>>> syntax could completely flip this logic, but making the initializer >>>>>>>>> essentially a static function that returns an object. In this case the >>>>>>>>> initializer could be made to specify the return type (that is the >>>>>>>>> supertype >>>>>>>>> of all possible factory-created objects) and assigning to self would >>>>>>>>> be >>>>>>>>> forbidden because there is not self yet: >>>>>>>>> >>>>>>>>> extension MyProtocol { >>>>>>>>> >>>>>>>>> public factory init(weCool: Bool) -> MyProtocol { >>>>>>>>> self = MyImpl() // error: cannot assign to `self` in a factory >>>>>>>>> initializer >>>>>>>>> self.init(...) // error: cannot make a delegating initializer call >>>>>>>>> in a factory initializer >>>>>>>>> if weCool { >>>>>>>>> return MyCoolImpl() >>>>>>>>> } else { >>>>>>>>> return MyUncoolImpl() >>>>>>>>> } >>>>>>>>> } >>>>>>>>> >>>>>>>>> } >>>>>>>>> >>>>>>>>> # In-place Member Initializers >>>>>>>>> >>>>>>>>> In addition, member initialization currently is only possible with >>>>>>>>> #2 (as in `self.member = value`), which could be extended in a >>>>>>>>> non-factory >>>>>>>>> initializer to be initializable in-place like this: >>>>>>>>> >>>>>>>>> self.member.init(...) >>>>>>>>> >>>>>>>>> This would compliment the delegating initialization syntax, while >>>>>>>>> giving a more reliable performance guarantee that this member will >>>>>>>>> not be >>>>>>>>> copy-initialized. >>>>>>>>> >>>>>>>>> On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <[email protected]> wrote: >>>>>>>>> >>>>>>>>> If `self` is not of type `inout Self?`, then what is the type of >>>>>>>>> `self` such that you may assign it a value of `nil`? >>>>>>>>> >>>>>>>>> It certainly cannot be of type `inout Self`, unless `Self` >>>>>>>>> conforms to `ExpressibleByNilLiteral`, in which case you are able to >>>>>>>>> assign >>>>>>>>> `self = nil` an unlimited number of times–but that has a totally >>>>>>>>> different >>>>>>>>> meaning. >>>>>>>>> >>>>>>>>> Could `self` be of type `inout Self!`? Now that implicitly >>>>>>>>> unwrapped optionals are no longer their own type, I’m not sure that’s >>>>>>>>> possible. But even if it were, that seems unintuitive and potentially >>>>>>>>> error-prone. >>>>>>>>> >>>>>>>>> So I think Greg is quite right that, to enable this feature, >>>>>>>>> `self` would have to be of type `inout Self?`–which is intriguing but >>>>>>>>> potentially more boilerplatey than the status quo. >>>>>>>>> On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution < >>>>>>>>> [email protected]> wrote: >>>>>>>>> >>>>>>>>>> Good point, but not necessarily. >>>>>>>>>> Since you cannot access `self` before it being fully initialized >>>>>>>>>> and since `self` can only be initialized once, this would mean that >>>>>>>>>> after >>>>>>>>>> `self = nil`, you won't be allowed to access `self` in your >>>>>>>>>> initializer at >>>>>>>>>> all.You'll be able to do any potential, cleanup though. >>>>>>>>>> Also, since there can be only one `self = nil`, there's no reason >>>>>>>>>> to treat `self` as `inout Self?`, because the only place it can be >>>>>>>>>> `nil` is >>>>>>>>>> the place it cannot be accessed any more. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Jun 9, 2017, at 7:45 AM, Greg Parker <[email protected]> >>>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution < >>>>>>>>>> [email protected]> wrote: >>>>>>>>>> >>>>>>>>>> 1. Arbitrary `self` Assignments In Intializers >>>>>>>>>> >>>>>>>>>> The first ideas is to allow `self = nil` inside failable >>>>>>>>>> initializers (essentially making `self` look like `inout Self?` >>>>>>>>>> instead of >>>>>>>>>> `inout Self` with magical `return nil`), so that all initializers >>>>>>>>>> uniformly >>>>>>>>>> can be written in `self = ...` form for clarity and convenience >>>>>>>>>> purposes. >>>>>>>>>> This should, theoretically, be nothing but a `defer { return nil }` >>>>>>>>>> type of >>>>>>>>>> rewrite, so I don't see any major difficulties implementing this. >>>>>>>>>> This is >>>>>>>>>> especially useful for failable-initializing enums where the main >>>>>>>>>> switch >>>>>>>>>> simply assigns to self in all cases and the rest of the initializer >>>>>>>>>> does >>>>>>>>>> some post-processing. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> I don't see how to avoid source incompatibility and uglification >>>>>>>>>> of failable initializer implementations here. Allowing `self = nil` >>>>>>>>>> inside >>>>>>>>>> a failable initializer would require `self` to be an optional. That >>>>>>>>>> in turn >>>>>>>>>> would require every use of `self` in the initializer to be >>>>>>>>>> nil-checked or >>>>>>>>>> forced. I don't think that loss everywhere outweighs the gain of >>>>>>>>>> `self = >>>>>>>>>> nil` in some places. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> Greg Parker [email protected] Runtime Wrangler >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> _______________________________________________ >>>>>>>>>> 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 >>>> >>>> >>>> >>>> >>>> _______________________________________________ >>>> 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 >>>> >>>> >>>> _______________________________________________ >>>> 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
