Allowing mutable members in structs


(Dan Raviv) #1

Would it make sense to allow mutable properties in structs, which could be
mutated even by non-mutating methods?

I've noticed this could be useful when implementing a non-mutating protocol
method. The method semantically doesn't change the state of the protocol's
implementor, and therefore shouldn't be declared as mutating. However,
*some* implementations might need to change some internal state for
implementing the functionality. Making specific struct properties mutable
for such a case could make sense.

Alternatively, Swift could allow implementing a non-mutating protocol
method as a mutating method in the implementor. Currently, this doesn't
seem to be allowed; Swift doesn't recognize the mutating method as a match
for the non-mutating protocol method.

Cheers,
Dan


(Joe Groff) #2

We currently have the property that, even in generic code, we can assume that an immutable value of type T is safe from read-read races, either because all types are never changed by immutable operations or are accessed through runtime calls with the appropriate synchronization (retain/release, weak references). To preserve these 'let' semantics with mutable fields, it would have to be the implementor's responsibility to ensure its mutating accesses are properly synchronized. Note that you can already get the effect of a mutable field in a struct by embedding a reference to a mutable class reference:

struct Foo {
  var x: Int
  class MutableFields {
    var y: Int
    init(y: Int) { self.y = y }
  }

  private var mutableFields: MutableFields
  var y: Int {
    get { return mutableFields.y }
    set { mutableFields.y = newValue }
  }
}

This can for instance be used to implement a memoized lazy field, as in https://github.com/robrix/Memo.

-Joe

···

On Mar 11, 2016, at 2:38 AM, Dan Raviv via swift-evolution <swift-evolution@swift.org> wrote:

Would it make sense to allow mutable properties in structs, which could be mutated even by non-mutating methods?

I've noticed this could be useful when implementing a non-mutating protocol method. The method semantically doesn't change the state of the protocol's implementor, and therefore shouldn't be declared as mutating. However, *some* implementations might need to change some internal state for implementing the functionality. Making specific struct properties mutable for such a case could make sense.

Alternatively, Swift could allow implementing a non-mutating protocol method as a mutating method in the implementor. Currently, this doesn't seem to be allowed; Swift doesn't recognize the mutating method as a match for the non-mutating protocol method.


(Radek Pietruszewski) #3

Would it make sense to allow mutable properties in structs, which could be mutated even by non-mutating methods?

This would break the whole mutability model of structs. The whole idea is: structs are always immutable, and you can mark things as “mutable”, but this can only happen if a struct is assigned to a mutable variable.

— Radek

···

On 11 Mar 2016, at 11:38, Dan Raviv via swift-evolution <swift-evolution@swift.org> wrote:

Would it make sense to allow mutable properties in structs, which could be mutated even by non-mutating methods?

I've noticed this could be useful when implementing a non-mutating protocol method. The method semantically doesn't change the state of the protocol's implementor, and therefore shouldn't be declared as mutating. However, *some* implementations might need to change some internal state for implementing the functionality. Making specific struct properties mutable for such a case could make sense.

Alternatively, Swift could allow implementing a non-mutating protocol method as a mutating method in the implementor. Currently, this doesn't seem to be allowed; Swift doesn't recognize the mutating method as a match for the non-mutating protocol method.

Cheers,
Dan
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Adrian Kashivskyy) #4

I agree with Radek, -1 on this.

Pozdrawiam – Regards,
Adrian Kashivskyy

···

Wiadomość napisana przez Radosław Pietruszewski via swift-evolution <swift-evolution@swift.org> w dniu 11.03.2016, o godz. 12:26:

Would it make sense to allow mutable properties in structs, which could be mutated even by non-mutating methods?

This would break the whole mutability model of structs. The whole idea is: structs are always immutable, and you can mark things as “mutable”, but this can only happen if a struct is assigned to a mutable variable.

— Radek

On 11 Mar 2016, at 11:38, Dan Raviv via swift-evolution <swift-evolution@swift.org> wrote:

Would it make sense to allow mutable properties in structs, which could be mutated even by non-mutating methods?

I've noticed this could be useful when implementing a non-mutating protocol method. The method semantically doesn't change the state of the protocol's implementor, and therefore shouldn't be declared as mutating. However, *some* implementations might need to change some internal state for implementing the functionality. Making specific struct properties mutable for such a case could make sense.

Alternatively, Swift could allow implementing a non-mutating protocol method as a mutating method in the implementor. Currently, this doesn't seem to be allowed; Swift doesn't recognize the mutating method as a match for the non-mutating protocol method.

Cheers,
Dan
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Charles Constant) #5

In general, I like things the way they are.

The only exception to this is that it would be nice occasionally to have an
easy way to make mutable computed property.

For example, to allow "array.first" or "array.last" to be mutable.

I have a feeling this would be difficult to implement (i.e.: most of Swift
is designed to pass values and structs as copies, so within your getter if
you as much as "var tempA = a" you ave a copy). Having said that, I have
had occasions where not being able to do so has annoyed me.


(Charles Constant) #6

... just to clarify my last comment.

Maybe "array.first" and "array.last" is a bad example, since it was
probably a design choice to make them "read only"

Here's a contrived example of what sometimes irritates me:

*struct Foo {*
* var point = CGPoint( x:0, y:0 )*
* var prop: CGPoint {*
* return self.point*
* }*
*}*

*var foo = Foo()*

*foo.prop.x = 10 // illegal*

When I'm writing something like this, it does make me wish I could tell the
compiler to send "prop" by reference. If I'm just creating the getter as a
convenience to find the correct property (like .first) it's a bit of a drag
to fill out the setter side also.


(Charles Constant) #7

What I would find ideal is to keep everything else the same, but add:

struct Foo {
var point = CGPoint( x:0, y:0 )
*inout* prop: CGPoint {
return *&*self.point
}
}

var foo = Foo()

foo.prop.x = 10