Swift中的FlatMap和Init

Pra*_*tha 3 functional-programming ios flatmap swift

结构

我尝试在dotSwift 2016 Demo中重新创建Chris Edihoff演示的代码.这是代码.

struct List {
    let name:String
    let id:Int
}

extension List {
    init?(json: [String:AnyObject]) {
        guard
            let name = json["name"] as? String,
            let id = json["id"] as? Int else
        {
            return nil
        }
        self.name = name
        self.id = id
    }
}

let listData = json["data"] as? [[String:AnyObject]]
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切似乎都很好.但这就是问题所在.他做了这样的事情:

let list:[List] = listData.flatMap(List.init)
Run Code Online (Sandbox Code Playgroud)

上面的行应该是返回列表对象的数组.Chris Edihoff似乎没有遇到任何问题,但是当我这样做时,Xcode警告说

- flatMap生成'U?',而不是预期的上下文结果类型'_?

还有什么在List.init这里?我从未见过这种初始化对象的方式.它应该是List()或者如果我们在这里使用客户初始化,那应该是List(json:someObject)对的吗?

参考Chris Edihof讲座:https://www.youtube.com/watch?v = ewk-XNzXzAA

小智 7

此代码无法编译的原因不同.首先,您不需要下标json["data"]- 迭代数据并初始化列表将成为flatMap的工作.

我在原始演示文稿中看到,listData.flatMap跟随一个if let块; 意思是listData将被解包而不是nil.

相反,在你的代码中,你有let listData = json as? [[String:AnyObject]].您的listData是类型的可选项[[String:AnyObject]]?.
那么,解决这个问题的方法是:

if let listData = json as? [[String:AnyObject]] {
   let list = listData.flatMap(List.init)
   //do something with list
}
Run Code Online (Sandbox Code Playgroud)

这里,listData的类型正确:[[String: AnyObject]].

关于List.init,它只是一种将初始化程序显式应用于flatMap提供的方法.您可以用更详细的方式重写该函数 - 但可能更清晰:

listData.flatMap {data in List(json: data)}
Run Code Online (Sandbox Code Playgroud)