下面函数'parseB'中用于flatMap的语法使用括号,而不是大括号。
struct Episode {
let id: String
let title: String
}
extension Episode {
init?(dictionary: [String: AnyObject]) {
guard let id = dictionary["id"] as? String, title = dictionary["title"] as? String else { return nil }
self.id = id
self.title = title
}
}
func parseA(dictionaries: [[String: AnyObject]]) -> [Episode] {
return dictionaries.flatMap { dic in Episode.init(dictionary: dic)}
}
func parseB(dictionaries: [[String: AnyObject]]) -> [Episode] {
return dictionaries.flatMap (Episode.init)
}
有一个看起来像这样的平面地图实现
public func flatMap<U>(@noescape f: (Wrapped) throws -> U!) rethrows -> U!
阅读本文我仍然无法理解,在上面的例子中,剧集上的init没有括号。
有时候,斯威夫特非常擅长推断内容很难理解正在发生的事情。有人可以帮我理解为什么剧集的init方法不使用括号吗?
...flatMap (Episode.init)
参考1:https://talk.objc.io/episodes/S01E01-networking 参考2:https://github.com/objcio/S01E01-networking
答案 0 :(得分:3)
让我们从一个简单的代码片段开始
[1,2,3].map(String.init) // ["1", "2", "3"]
这里map
遍历数组的每个元素[1,2,3],每次都将第n个元素传递给String
初始化器。
这是因为
Int
作为通用元素String
有一个init接受Int
仅作为参数( ... )
代替{ ... }
?在这种情况下,我们使用此.map(...)
而不是此.map{ ... }
,因为我们将map
传递给其他地方定义的函数(以及初始值设定项),我们不直接编写函数/闭合。
就像我们写的那样
func isEven(n:Int) -> Bool {
return n % 2 == 0
}
[1,2,3].filter(isEven) // [2]
这里我们将过滤上面定义的函数,因此我们使用()
。
当然我们也可以使用{ ... }
[1,2,3].filter { (n:Int) -> Bool in
return n % 2 == 0
}
在您的代码中,这可行
dictionaries.flatMap (Episode.init)
因为Episode
有一个init
,它接受dictionaries
中相同类型的元素。
事实上,dictionaries
的每个元素都具有此类型[String: AnyObject]
,并且Episode的init接受相同的类型。
init?(dictionary: [String: AnyObject]) { ... }
答案 1 :(得分:1)
那是因为在Swift中,instance methods are curried functions。这意味着Episode.init
是一个函数(实际上它是一个命名的闭包),它接收一个参数 - self
,它恰巧(或不匹配)匹配flatMap
期望的闭包的签名。 / p>
您的代码中发生的事情是您传递对flatMap
期望的闭包的引用,而不是调用它,因为调用闭包只会返回一个Episode
实例。
答案 2 :(得分:1)
尾随关闭快速您可以在Apple文档中找到它 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html
flatMap
等待类型为(A)->B
的参数,但它可以是函数或闭包:
let initializer: (Int) -> String = String.init
相同
let closure:(Int) -> String = {return String($0)}
为简单起见,我们可以调用map
方法:
[1,2,3].map(initializer) == [1,2,3].map(closure)
但是如果我们使用closure是最后一个参数,它可以写在方法之外,在我们的例子中map
方法
[1,2,3].map(){return String($0)}
我们可以省略()
:
[1,2,3].map{return String($0)}
答案 3 :(得分:0)
class Employee {
var name: String = ""
init(name: String) {
self.name = name
}
}
实例方法是Swift中的Curried函数
这是一个curried函数,它接受一个参数String并返回一个Employee
let employeeFunc = Employee.init // (String) -> Employee
让我们在数组类型
上定义我们自己的地图功能extension Array {
func myMap <U> (f: (Element) -> U) -> [U] {
var result = [U]()
for element in self {
result.append(f(element))
}
return result
}
}
var allEmployee = [Employee]()
let names = ["Mario", "Luigi"]
您可以一次将值传递给curried函数。这个curried函数只期望一个参数
let firstEmployee = employeeFunc("Superman")
同样,我们可以将多个名称传递给多个Employee来创建实例
allEmployee = names.myMap(f: employeeFunc)
我们也可以这样映射
allEmployee = names.myMap(){ employeeFunc($0)}
让我们打印值
for employee in allEmployee {
print (employee.name)
}