I'm trying to use the reducefunction on an array:
var fields = ["gender", "name", "nickname"]
var stats = fields.reduce([String:String]()) { (res, field) -> [String:String] in
  res[field] = json[field] ?? ""
  return res
}
It's just going through the fields array and assigns values from json object to res.
Seems simple to me but the compiler keeps saying:
error: cannot assign through subscript: 'res' is a 'let' constant
on the line:
res[field] = json[field] ?? ""
It doesn't make any sense to me because I've never specified res or stats as let.
Closure parameters (unless declared with inout) are implicitly constants, as if declared with let.
If you want to modify it then you have to make mutable copy first:
let stats = fields.reduce([String:String]()) { (res, field) -> [String:String] in
    var res = res
    res[field] = json[field] ?? ""
    return res
}
As of Swift 4 you can use reduce(into:_:):
let stats = fields.reduce(into: [String:String]()) { (res, field) in
    res[field] = json[field] ?? ""
}
Here res is an "inout" parameter and can be mutated in the closure.
This is far more efficient, because no copies are made in each
iteration step.
See also SE-0171 Reduce with inout.
A different Swift 4 solution would be create a new dictionary by mapping each field to a key/value pair:
let stats = Dictionary(uniqueKeysWithValues: fields.map { ($0, json[$0] ?? "") })
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With