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