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

Reply via email to