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

Reply via email to