Add syntactic support for mutable return values from value types/structs methods

Currently the Swift language does not allow for a mutable return value of a function on a value type. If you attempt to call a mutating func directly on the result of a function that reutrns a value type you will be met with the following:

error: cannot use mutating member on immutable value: function call returns immutable value

I am interested to find what people think of potentially introducing the ability to specify on a function that it can return a mutable value, or potentially at the call-site specify that you want this behaviour.

For example:

 struct ValueType {
    
    var value: String
    var entries: [String]
    
    mutating func modifying(name: String) -> mutating ValueType {
        value = name
        return self
    }
    
    mutating func appending(entry: String) -> mutating ValueType {
        entries.append(entry)
        return self
    }
}

var myType = ValueType(value: "Initial", entries: [])

myType
    .modifying(name: "Countries")
    .appending(entry: "UK")
    .appending(entry: "USA")

Or potentially instead,

myType.mutatable
    .modifying(name: "Countries")
	.appending(entry: "UK")
	.appending(entry: "USA")

The justification for this would be to allow for builder-type patterns to be applied to value types and also enable more expressive/readable code at the call-site.

A standard library use-case for this would be to add an 'appending' function to Array, that returns the array after it has been modified.

I don't have a great understanding of how this would be implemented or the potential overhead in terms of performance this would cost so I look forward to hearing feedback!

1 Like

I'm not sure I understand what the problem is. Can't you have a builder pattern with value types already?

struct ValueType {
    var name: String = ""
    var numbers: [Int] = []

    func appending(number: Int) -> ValueType {
        var copy = self
        copy.numbers.append(number)
        return copy
    }

    func modifying(name: String) -> ValueType {
        var copy = self
        copy.name = name
        return copy
    }
}    


let value = ValueType()
                 .modifying(name: "Fritz")
                 .appending(number: 3)

print(value.name)
// Fritz
print(value.numbers)
// [3]
1 Like

Ah I see. That's my lack of understanding here.

So what I've noticed is, you can't use the builder approach if a func is mutating as it will return an immutable value.

E.g. If we add mutating to your calls, and either, just do what you did in your example, or mutate self and then return a mutable copy. We get the error.

If you want a Builder, then why do you want it to be a struct?

Initially it was because I was extending an existing value type (URLRequest).