I wrote a draft of a partial initializer proposal back in January or February of last year. If you're thinking of re-introducing that topic you might want to take a look at it. You can find it here: https://github.com/anandabits/swift-evolution/blob/partial-initializers/proposals/NNNN-partial-initializers.md. There was some discussion on the list as well. You might want to look up that conversation in the archives.
Sent from my iPad > On Jun 25, 2017, at 2:24 PM, Robert Bennett via swift-evolution > <[email protected]> wrote: > > You’re right Xiaodi, I did not entirely think this through. However I think > this could still work with another addition to the language: partial > initializers. These would be treated as initializers are now (meaning, for > instance, no reference to self until initialization is complete) except they > would only need to initialize a subset of the instance variables before > exiting. An initializer could then satisfy the requirement that all instance > variables must be initialized by calling partial initializers. > > By incorporating partial initializers, it would be possible to guarantee that > a `let` variable in a protocol is only set once. This is because an init > implemented in a protocol extension could delegate to a partial initializers > required by the protocol, and because they are only partial initializers, > they need not set the instance variables already set in the initializer; it > would be up to a conforming type to ensure this is the caee. A confirming > type would define the partial initializer to set everything not already set > in the protocol extension’s init, and it would be a compiler error to set a > variable in the partial initializer that is already set in the extension’s > init without overriding the extension’s init. Example code: > > protocol P { > var x: Int { let } // or { get set(init) }, or whatever > > partialinit initializeRest() > init() > } > > extension P { > init() { > initializeRest() > self.x = 1 > } > } > > struct S: P { > let x: Int > var y: String > > // It would be a compiler error to set x here without also redefining > init() > partialinit initializeRest() { > self.y = “P has no knowledge of me” > } > > // Can use default init provided by P > } > >> On Jun 23, 2017, at 8:12 PM, Karl Wagner <[email protected]> wrote: >> >> What you want is some way to guarantee value semantics when writing generic >> code. >> >> It’s a known hole, and admittedly quite a big one. I hope that there will be >> time for core language improvements like this in Swift 5. Be sure to raise >> the issue again once planning for that starts! >> >> - Karl >> >>> On 23. Jun 2017, at 23:43, Robert Bennett via swift-evolution >>> <[email protected]> wrote: >>> >>> Hello Swift Evolution, >>> >>> I’m bumping into an annoying problem with protocols. In a class or struct >>> it is common to have a `let` instance variable and assign it in `init`. >>> Unfortunately there is no way to translate this into a protocol with init >>> in an extension. If attempting to set the variable in init in an extension, >>> it must be of type { get set }, which means it cannot be a `let` constant >>> in the conforming type. AFAIK there is no way around this — if you want to >>> set an instance variable in an initializer in a protocol extension, it must >>> be marked as { get set }. The alternative is to write the initializer >>> separately for each adopting type, but this violates DRY. >>> >>> Hence, I am proposing a third option to go along with `get` and `set` in a >>> protocol. This would indicate that the variable can be a constant, but is >>> settable in an initializer. In this case, the conforming type *must* use >>> `let` to declare the variable. >>> >>> Option 1: the keyword `let`. If present, it would need to be the only thing >>> in the curly brackets because it simultaneously implies `get` and not `set`. >>> >>> protocol P { >>> var x: Int { let } >>> init(_ x: Int) >>> func modifyX() >>> } >>> extension P { >>> init(_ x: Int) { >>> self.x = x // This is ok; would not be ok if x were marked { get } >>> } >>> >>> func modifyX() { >>> self.x += 1 // Not allowed >>> } >>> } >>> >>> struct S: P { >>> let x: Int // This is ok; would not be ok if x were marked { get set } >>> } >>> >>> Option 2: `set(init)`. Can (and often will) coexist with `get`. >>> >>> protocol P { >>> var x: Int { get set(init) } >>> init(_ x: Int) >>> func modifyX() >>> } >>> extension P { >>> init(_ x: Int) { >>> self.x = x // This is ok; would not be ok if x were marked { get } >>> } >>> >>> func modifyX() { >>> self.x += 1 // Not allowed >>> } >>> } >>> >>> struct S: P { >>> let x: Int // This is ok; would not be ok if x were marked { get set } >>> } >>> >>> >>> I’d like to hear all of your thoughts on this. >>> >>> Best, >>> Robert >>> _______________________________________________ >>> 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
