使用可选项时的模式往往是:
if let thing = optionalThing { return doThing(thing) } else { return nil }
这个成语用标准库函数图简洁地处理
map(optionalThing) { thing in doThing(thing) }
然后,本书继续介绍可选绑定的概念,这就是我的区分能力开始分解的地方.
本书引导我们定义地图功能:
func map<T,U>(optional: T?,f: T -> U) -> U? { if let x = optional { return f(x) } else { return nil } }
并指导我们定义一个可选的绑定功能.注意:本书使用运算符>> =,但是我选择使用命名函数,因为它有助于我看到相似之处.
func optionalBind<T,f: T -> U?) -> U? { if let x = optional { return f(x) } else { return nil } }
这两种方法的实现与我相同.两者之间唯一的区别就是它们的功能参数:
> map需要一个将T转换成U的函数
> optionalBind需要一个将T转换为可选U的函数
func addOptionalsBind(optionalX: Int?,optionalY: Int?) -> Int? { return optionalBind(optionalX) { x in optionalBind(optionalY) { y in x + y } } } func addOptionalsMap(optionalX: Int?,optionalY: Int?) -> Int? { return map(optionalX) { x in map(optionalY) { y in x + y } } }
> addOptionalsBind函数完全符合你期望做的事情.
> addOptionalsMap函数无法编译说明:
‘Int??’ is not convertible to ‘Int?’
我觉得我很接近于理解这里发生了什么(可选整数被再次包装在可选中)但是如何呢?为什么?hu?),但是我还远远不够,我不完全确定一个聪明的问题要问.
let mappedInternal: Int? = map(optionalY) { (y: Int) -> Int in return x + y }
提供给映射的闭包采用Int并返回Int,而对map的调用本身返回一个可选的:Int?没有惊喜!让我们走一步,看看会发生什么:
let mappedExternal: ??? = map(optionalX) { (x: ???) -> ??? in let mappedInternal: Int? = map(optionalY) { (y: Int) -> Int in return x + y } return mappedInternal }
这里我们可以从上面看到我们的mappedInternal值,但是还有一些类型不定义.地图具有(T 1,T→U) – >的签名. U,所以我们只需要弄清楚这种情况下T和U是什么.我们知道闭包的返回值mappedInternal是一个Int?,所以U变成Int?这里.另一方面,T可以保留不可选的Int.代替,我们得到这个:
let mappedExternal: Int?? = map(optionalX) { (x: Int) -> Int? in let mappedInternal: Int? = map(optionalY) { (y: Int) -> Int in return x + y } return mappedInternal }
封闭物是T→ U,其评估为Int→ Int?,整个地图表达式结束映射Int?到国际?不是你所想的!
与使用optionalBind的版本对比,完全类型指定:
let boundExternal: ??? = optionalBind(optionalX) { (x: ???) -> ??? in let boundInternal: Int? = optionalBind(optionalY) { (y: Int) -> Int? in return x + y } return boundInternal }
我们来看看那些?该版本的类型.对于optionalBind,我们需要T – > ü?关闭,并有一个Int?在boundInternal中返回值.所以在这种情况下,T和U都可以是Int,我们的实现如下所示:
let boundExternal: Int? = optionalBind(optionalX) { (x: Int) -> Int? in let boundInternal: Int? = optionalBind(optionalY) { (y: Int) -> Int? in return x + y } return boundInternal }
您的混淆可能来自变量可以“取消”作为可选项的方式.使用单层时很容易看到:
func optionalOpposite(num: Int?) -> Int? { if let num = num { return -num } return nil }
可以使用类型为Int的变量(如它显式期望的)或Int类型的非可选变量来调用optionalOpposite.在第二种情况下,非可选变量在调用期间被隐式转换为可选(即,解除).
地图(x:T,f:T→U)→> ü?正在提升其回报价值.由于f被声明为T – > U,它不会返回一个可选的U?然而地图的返回值为U?意味着f(x)被提升到U?回来
在你的例子中,内部关闭返回x y,这个int被提升到Int?那个值再次被提升到Int?导致类型不匹配,因为你已经声明了addOptionalsMap来返回一个Int?