Optional类型调用flatMap时闭包内解包报错问题咨询
问题分析与解决办法
报错原因
嘿,这个问题我之前也踩过坑,咱们一步步拆解来看:
先看你出错的代码:
foo.flatMap { $0 + bar.flatMap(id) }
这里核心是类型不匹配:
foo.flatMap的闭包参数$0是已解包的Int——因为flatMap的特性就是:只有当foo非nil时才会执行闭包,并且自动把可选值拆成原始类型传给闭包。- 而
bar.flatMap(id)返回的是Int?——不管bar是nil还是有值,flatMap的返回值始终是可选类型。
Swift的+运算符要求两个操作数都是非可选的Int,你现在把Int和Int?硬凑在一起相加,编译器肯定会报错,提示你可选类型没解包。
至于你单独调用foo.flatMap(id)能成功,是因为Swift的类型隐式转换:flatMap接受的转换函数可以返回U?,而你的id函数返回的是T,Swift会自动把T包装成T?,刚好匹配flatMap的要求。
解决办法
如果你想要的是只有foo和bar都非nil时才返回它们的和,否则返回nil,这正是flatMap处理多个可选值组合的标准场景,用嵌套flatMap就能解决:
var foo: Int? = 1 var bar: Int? = 2 // 完整写法 let result = foo.flatMap { fooValue in bar.flatMap { barValue in fooValue + barValue } }
或者用更简洁的尾随闭包写法:
let result = foo.flatMap { fooVal in bar.flatMap { fooVal + $0 } }
原理很简单:外层flatMap先处理foo,只有foo非nil才会进入闭包;然后在闭包里用bar.flatMap处理bar,只有bar也非nil时,才会执行相加操作,最终返回包装成Int?的结果;只要foo或bar任意一个是nil,整个表达式就会返回nil,完全符合组合可选值的需求。
如果你的场景允许给bar设置默认值(比如bar为nil时用0相加),也可以用nil合并运算符??:
let result = foo.flatMap { $0 + (bar ?? 0) }
但要注意,这种情况下即使bar是nil,只要foo非nil,就会返回$0 + 0的结果,而不是nil,和纯组合可选值的逻辑不同,根据你的实际需求选择就行。
内容的提问来源于stack exchange,提问作者Brian Cully
相关产品推荐
相关产品推荐

