How to mutate structs in Swift using map?

There are exactly two cases where the Swift compiler infers the return
type of a closure automatically:

  • In a “single-expression closure,” i.e. the closure body
    consists of a single expression only (with or without explicit
    closure parameters).
  • If the type can be inferred from the calling context.

None of this applies in

let inActionPersons = persons.map { (var p) in
    p.active = false
    return p
}

or

let a = persons.map { p in
        var p1 = p
        p1.active = false
        return p1
}

and that’s why
you have to specify the return type explicitly as in Kametrixom’s answer.

Example of a single-expression closure:

let inActionPersons = persons.map { p in
    Person(firstName: p.firstName, lastName: p.lastName, active: false)
}

and it would compile with (var p) in or (p : Person) in as well, so this has nothing to do with whether the closure arguments are given
explicitly in parentheses or not.

And here is an example where the type is inferred from the calling
context:

let a : [Person] = persons.map { p in
    var p1 = p
    p1.active = false
    return p1
}

The result of map() must be a [Person] array, so map needs
a closure of type Person -> Person, and the compiler infers
the return type Person automatically.

For more information, see “Inferring Type From Context” and “Implicit Returns from Single-Expression Closures” in the
“Closures” chapter in the Swift book.

Leave a Comment