Reputation: 2513
Below is some playground code that I am using to explore the behavior of Array's implementation of the Sequence protocol's flatMap() method. I was surprised to discover that a consequence of declaring callFlatmap's array parameter as an Array of Any is that flatMap wraps the arguments to the transform closure in an optional. Is this behavior by design?
func echo<T>(_ arg: T) -> T {
print("arg = \(arg)")
return arg
}
func callFlatten(_ array: Array<Any>) {
print("Input: \(array)")
print("Result: \(array.flatMap{ echo($0) })\n\n")
}
var array = [[1, 2], [3, 4], [5, 6]]
callFlatten(array)
/* Prints:
Input: [[1, 2], [3, 4], [5, 6]]
arg = Optional([1, 2])
arg = Optional([3, 4])
arg = Optional([5, 6])
Result: [[1, 2], [3, 4], [5, 6]]
*/
print("Input: \(array)")
print("Result: \(array.flatMap{ echo($0) })\n\n")
/* Prints:
Input: [[1, 2], [3, 4], [5, 6]]
arg = [1, 2]
arg = [3, 4]
arg = [5, 6]
Result: [1, 2, 3, 4, 5, 6]
*/
Upvotes: 1
Views: 109
Reputation: 539745
Array
has two flatMap
methods:
/// Returns an array containing the concatenated results of calling the
/// given transformation with each element of this sequence.
public func flatMap<SegmentOfResult : Sequence>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Iterator.Element]
and
/// Returns an array containing the non-`nil` results of calling the given
/// transformation with each element of this sequence.
public func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
In
var array = [[1, 2], [3, 4], [5, 6]]
// ...
print("Result: \(array.flatMap{ echo($0) })\n\n")
// Result: [1, 2, 3, 4, 5, 6]
the first method is called, because the array element type is known
to be an array and thus a Sequence
. echo($0)
is called with
each element, and the result is the concatenation of the inner arrays.
In
func callFlatten(_ array: Array<Any>) {
print("Input: \(array)")
print("Result: \(array.flatMap{ echo($0) })\n\n")
}
callFlatten(array)
// Result: [[1, 2], [3, 4], [5, 6]]
nothing is known about the element type, and the second method
is called.
In order to match the return type ElementOfResult?
of the closure,
the generic placeholder type of T
of echo
is inferred as
Any?
and $0
is promoted to an optional.
The result is an array with the non-nil results of echo($0)
– which are exactly the array elements again. The type of the result is Array<Any>
.
Upvotes: 1