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 inout
s).
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.