Home > Net >  Using reduce() with an inferred return type
Using reduce() with an inferred return type

Time:06-21

Given:

let a = [1, 2, 3]

Use reduce() to map to an array of strings:

let b: [String] = a.reduce([], { $0   [String($1)] })

This returns ["1", "2", "3"] as you'd expect.

let c: [String] = a.reduce([], { $0   [$1] })

This generates a compiler error (can't convert from Int to String), also as you'd expect.

let d = a.reduce([String](), { $0   [$1] })

This returns [1, 2, 3] of type Array<Any>. Why doesn't the compiler consider the Result type to be Array<String>, and also generate an error in this case?

CodePudding user response:

[Any] is a type of array that can contain 1, 2 and 3. When you try to append those values to [String] it just turns it into [Any].

It doesn't work on the other case because you're asking for the final array to be [String] by using it on the declaration.

let a = // array of [Int] ✅
let b: [String] = // array of [String] ✅
let c: [String] = // array of [Any] ❌
let d = // array of [Any] ✅

CodePudding user response:

You want an error to occur (and I think a warning is in order), but the compiler assumes you want code to compile, instead. So it's going to fall back to Any for heterogenous collections, unless you type it otherwise. E.g.

protocol Protocol { }
extension Bool: Protocol { }
extension Int: Protocol { }

[[true]].reduce([0],  ) as [any Protocol]

The correct return type can be inferred. Just not if you create a heterogeneous result.

a.map(String.init)
a.reduce(into: [String]()) { $0.append(.init($1)) }
a.reduce(into: []) { $0.append(String($1)) }
  • Related