Junkor

FlatMap Optionals

文章翻译自objc,原文连接:『FlatMap Optionals

之前我们讲过给数组绑定函数(前边的Flattening and Mapping Array)的知识,有时称作flatMap。我们可以对optional做同样的事情,让我们来看看下边的两个dictionary:

let populations = ["Paris": 2243, "Madrid": 3216, "Amsterdam": 881, "Berlin": 3397]
let capitals = ["France": "Paris", "Spain": "Madrid","The Netherlands": "Amsterdam", "Sweden": "Stockholm"]

如果我们想从dictionary中查找一个值,我们需要这样操作:

func populationOfCapital(country: String) -> Int? {
	if let capital = capitals[country] {
    	return populations[capital]
	}
	return nil
}

我们也可以用Map for Optionals来实现,我们只需要一个单一的返回值,不过它却返回了一个嵌套的optional:

func populationOfCapital2(country: String) -> Int?? {
	return capitals[country].map { populations[$0] }
}

对于这种使用函数链并需要一个optional返回值的场景,用flatMap是非常得心应手的:

func flatMap<A,B>(x: A?, y: A -> B?) -> B? {
	if let value = x {
    	return y(value)
	}
	return nil
}

现在就可以重构我们的populationOfCapital为只有一个单一返回值了:

func populationOfCapital3(country: String) -> Int? {
	return flatMap(capitals[country]) { populations[$0] }
}

此外,我们也可以用自定义操作符»=,像我们之前在中用的那样,用于链接调用多个函数。当你想在单行语句里使用多个flatMap操作的时候,使用操作符的优势就立刻彰显了:

func populationOfCapital4(country: String) -> Int? {
	return capitals[country] >>= { populations[$0] }
}