Путаница с закрытием .map transform - PullRequest
0 голосов
/ 09 июня 2019

Приведенный ниже код компилируется и выполняется нормально, и, кажется, указывает, что функции closure и String.init(describing:) полностью эквивалентны по своей сигнатуре, поскольку метод .map успешно принимает обе из них.

let someDict: [String: String] = [
    "string1" : "Hello",
    "string2" : "Bye",
]

//One way to call .map
var closure = { (key: String, value: String) -> String in
    return "The key is \(key), the value is \(value)"
}
someDict.map(closure)

//Another way to call .map
someDict.map(String.init(describing:))

Но как можно поместить в .map функцию String.init(describing:), которая является функцией только 1 аргумента, тогда как .map ожидает функцию из 2 аргументов?Или я что-то здесь неправильно понимаю ...

Кстати, проверка документации показывает, что она действительно ожидает функцию 2 аргументов:

transform: ((key: String, value: String)) throws -> T

1 Ответ

1 голос
/ 09 июня 2019

Кстати, проверка документации показывает, что она действительно ожидает функция 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:).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...