请考虑以下代码段:
var a: String? = "abc"
var b: String?
let result = [a, b].compactMap { $0 }
Run Code Online (Sandbox Code Playgroud)
执行后,result
将会
["abc"]
Run Code Online (Sandbox Code Playgroud)
这是预期的结果.这里的result(ElementOfResult
)元素是String
.
print(type(of: result))
Array<String>
Run Code Online (Sandbox Code Playgroud)
现在到了有趣的部分.将代码段更改为
var a: String? = "abc"
var b: Int?
let result = [a, b].compactMap { $0 }
Run Code Online (Sandbox Code Playgroud)
并执行它,result
将是
[Optional("abc"), nil]
Run Code Online (Sandbox Code Playgroud)
结果的元件(ElementOfResult
)这里是Any
这是有意义的,因为Any
是的公分母String
和Int
.
print(type(of: result))
Array<Any>
Run Code Online (Sandbox Code Playgroud)
为什么nil
返回的结果compactMap
与其定义相矛盾?
来自Apple的compactMap
文档
compactMap(_ :)
返回一个数组,其中包含使用此序列的每个元素调用给定转换的非零结果.
宣言
func compactMap(_ transform:(Self.Element)throws - > ElementOfResult?)rethrows - > [ElementOfResult]
这是因为[a, b]
被认为是[Any]
.当数组文字中的元素类型完全不相关(Int?
和String?
)时,数组类型被推断为[Any]
.
在传递给的闭包中compactMap
,你返回$0
了类型Any
.这意味着$0
永远不会nil
.数组中的所有选项都包含在Any
您将它们放入数组中的那一刻.因为你永远不会nil
在闭包中返回a ,所有元素都保留在结果数组中.
编译器可以警告您在非可选的Any
s中包装选项:
var a: String? = "abc"
let any: Any = a // warning!
Run Code Online (Sandbox Code Playgroud)
但不幸的是,它在您创建数组时不会发出警告.
无论如何,您可以通过指定您想要的内容来获得预期的行为[Any?]
:
let result = ([a, b] as [Any?]).compactMap { $0 }
Run Code Online (Sandbox Code Playgroud)
所以你有点打开它们Any
.
要么:
let result = [a as Any?, b as Any?].compactMap { $0 }
Run Code Online (Sandbox Code Playgroud)
为什么可选类型可以包含在
Any
?
根据文档(在类型转换Any
和AnyObject
部分):
Any
可以表示任何类型的实例,包括函数类型.
因此,Optional<T>
毫无疑问可以用Any
.
归档时间: |
|
查看次数: |
694 次 |
最近记录: |