Кстати, проверка документации показывает, что она действительно ожидает
функция 2 аргументов:
transform: ((key: String, value: String)) throws -> T
На самом деле нет. Обратите внимание на дополнительные скобки ()
. Это показывает, что она ожидает функцию, которая принимает один аргумент, который является кортежем, содержащим два элемента.
Рассмотрим этот пример:
// function foo takes two arguments
func foo(_ a: Int, _ b: Int) -> Int {
return a + b
}
// function bar takes one tuple with two elements
func bar(_ a: (Int, Int)) -> Int {
return a.0 + a.1
}
let f1 = foo
print(type(of: f1)) // (Int, Int) -> Int
let f2 = bar
print(type(of: f2)) // ((Int, Int)) -> Int
Итак, дополнительные скобки говорят нам, что map
ожидает один аргумент, который является кортежем, содержащим два элемента.
Замыкание, переданное в map
, всегда работает с одним элементом из последовательности за раз. Этот элемент может быть кортежем , таким как ваш случай, и тогда ваше закрытие может деконструировать , который кортежет в несколько значений.
Рассмотрим этот пример:
// tup is a tuple containing 3 values
let tup = (1, true, "hello")
// deconstruct the tuple through assignment
let (x, y, z) = tup
print(x) // 1
print(y) // true
print(z) // hello
Итак, в этом примере:
var closure = { (key: String, value: String) -> String in
return "The key is \(key), the value is \(value)"
}
someDict.map(closure)
Закрытию
map
присваивается кортеж в форме (key: String, value: String)
, и замыкание деконструирует его в key
и value
так же, как let
делал выше.
В этом примере:
someDict.map(String.init(describing:))
, что эквивалентно:
someDict.map({ String(describing: $0) })
map
берет весь кортеж и передает его String(describing:)
.