[Pitch] Shorthand binding-like properties for dictionaries

Hi everyone! There are times when we need to get the value from the dictionary and possibly store it. At the same time we want to write new values. In order to do this we have to always access the dictionary directly

dict["key"] // read
dict["key"] = 5 // write

An idea recently came to my mind which I wanted to share and maybe it gathers some interest from you folks.

So if we're to store the property, then we create a variable/constant like so: var value = dict["key"]. And then we can access it by value name. But if we're to update the value, we still got to access the dictionary directly and to me it feels a bit redundant.

So my idea is to have properties that work both as getters and setters for the particular value. Something like this:

inout var value = dict["key"]

value // returns 5
value = 6 // value is now 6

I also considered mutating keyword but then it resembles more of a mutating function that writes rather than reads – not exactly the emphasis I'd like to put here.

Technically it is already possible via Binding or get/set closures on properties

let value = Binding(get: { dict["key"] }, set: { dict["key"] = $0 })

value.wrappedValue // returns 5
value.wrappedValue = 6 // value is now 6

or

var value: Int {
    get { dict["key"] }
    set { dict["key"] = newValue }
}

value // returns 5
value = 6 // value is now 6

But it gets unnecessary long and I something like an inout keyword could help us be more concise. I'm aware that it has a different semantics from just storing a value from a dictionary in a property but most of the time, at least I am, anyways interested in the current value, I don't think it will hurt anything – people will need to learn the new technique and this semantics will just be part of the new approach.

I'm not very knowledgable in functional programming but I think this my suggestion resembles a Lens from over there – this might give some inspiration for the implementation or maybe even generalizing, although I haven't found any as-often-used use case other than with dictionary.

While writing this I realized that something like a property wrapper might solve it but dictionaries are structs, not sure how would I update the original copy from within the property wrapper. Also it will still not beat the shortness of a single keyword

Thank you for having a look, I'd be glad to discuss it in detail

3 Likes

I think this is related to the idea of a “mutable borrow” which has been discussed in some other threads recently.

One situation in which it would be a great help, is when the dictionary values are themselves a copy-on-write type such as Array. The naive approach of “fetch existing array value, modify it in some way, then write it back” will cause an unwanted copy of the entire array because the dictionary was still holding the original copy during the mutation.

1 Like

The ownership manifesto discusses this type of inout binding.

1 Like

oh interesting, thanks a lot, didn't know that! that looks very similar to my proposition although mine doesn't have to do anything with the Ownership model in Swift