Home > Enterprise >  Is there any way to make the method return a mutable value?
Is there any way to make the method return a mutable value?

Time:01-29

as shown in the code below:

struct Person {
    var name: String
}

struct Group {
    var person: Person
    
    func callAsFunction() -> Person {
        // Person is immutable value
        person
    }
}

var james = Person(name: "James")
var group = Group(person: james)
group().name = "Wong" //ERROR: Cannot assign to property: function call returns immutable value

group() return an immutable value, that can't be changed! So Is there any way to make the callAsFunction() method return a mutable value?

Thanks ;)


Updated:

My idea is to transfer all the calls and visits of the Group to the Person object in the Group, just like using Person directly.

I can't use dynamicMemberLookup because I don't know what method or property there will be in Person. For example, there may be 100 methods and properties in Person (not only one name property as demonstrated), and it is impossible for me to write 100 subscript methods with dynamicMemberLookup.

My needs are a bit like proxy objects in the Ruby language. Accessing an object (Group) actually accesses another object (Person) inside it, as if the Group does not exist.

ruby proxy patterns: enter image description here

If Person was a reference type, it would have worked, but not for a value type. And even if you took your value type, and first assigned it to a variable before mutating it, you would only be mutating your copy, not the original.

If you want the behavior you want, you would use a @dynamicMemberLookup as suggested by matt ( 1) and outlined in SE-0195.


You said:

I can't use dynamicMemberLookup because I don't know what method or property there will be in Person. For example, there may be 100 methods and properties in Person (not only one name property as demonstrated), and it is impossible for me to write 100 subscript methods with dynamicMemberLookup.

You do not need “100 subscript methods.” It is the motivating idea behind @dynamicMemberLookup, namely that the properties will be determined dynamically. E.g., here is Person with two properties, but Group only has the one @dynamicMemberLookup.

struct Person {
    var name: String
    var city: String
}

@dynamicMemberLookup
struct Group {
    var person: Person
    subscript(dynamicMember keyPath: WritableKeyPath<Person, String>) -> String {
        get { self.person[keyPath: keyPath] }
        set { self.person[keyPath: keyPath] = newValue }
    }
}

var group = Group(person: Person(name: "James", city: "New York"))
group.name = "Wong"
group.city = "Los Angeles"
print(group.person) // Person(name: "Wong", city: "Los Angeles")
  •  Tags:  
  • Related