In-place map for MutableCollection

In the adding toggle to bool thread, some good examples came up for why that is useful, and many of the same examples apply to this inout version as well. A big difference is that it allows you to not repeat your self. Here's a contrived example:

struct Favorite {
    var name: String
    var visible: Bool
}
var favorites: [String: [Favorite]] = [
    "john": [Favorite(name: "swift.org", visible: true), Favorite(name: "idris-lang.org", visible: false)],
    "edward": [Favorite(name: "haskell.org", visible: true)],
]

Let's say that we want to toggle all visible properties for the "john" key. Our new mapInPlace makes this quite easy.

favorites["john"]?.mapInPlace { $0.visible.toggle() }

The main difference in expressivity is that the inout allows you to both get and set a value. The way it composes is especially interesting: For example, in the closure body, $0 is inout, but because visible is a var, $0.visible is also inout. Likewise, the ? operator will also maintain the inout-ness of a value. (Technically, these are called l-values, not inouts).

This style allows you to reach "deep" into a data structure, and mutate it. In a functional style, mutating something that is slightly deeper into the data structure becomes very cumbersome, unless you use something like lenses. This deep mutation is something that comes up often in my code when dealing with data. We could also consider adding lenses to the Standard Library, but Swift already has strong support for inout throughout the language.

If you have a closure (A) -> A, you can always recover (inout A) -> () by prepending it with $0 = . If something like with would be in the Standard Library, the inout version could also be recovered from the functional version.

3 Likes