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
