Swift 当存储在可选变量中时,compactMap的行为不同
考虑以下数组Swift 当存储在可选变量中时,compactMap的行为不同,swift,xcode,functional-programming,swift4.1,Swift,Xcode,Functional Programming,Swift4.1,考虑以下数组 let marks = ["86", "45", "thiry six", "76"] 我已经在以下两个案例中解释了我的怀疑 案例1 // Compact map without optionals let compactMapped: [Int] = marks.compactMap { Int($0) } print("\(compactMapped)") 结果-[86,45
let marks = ["86", "45", "thiry six", "76"]
我已经在以下两个案例中解释了我的怀疑
案例1
// Compact map without optionals
let compactMapped: [Int] = marks.compactMap { Int($0) }
print("\(compactMapped)")
结果-[86,45,76]
案例2
// Compact map with optionals
let compactMappedOptional: [Int?] = marks.compactMap { Int($0) }
print("\(compactMappedOptional)")
结果-[可选(86)、可选(45)、无、可选(76)]
为什么案例2的结果为“零”?有人能解释为什么在第二种情况下不是这样的[可选(86)、可选(45)、可选(76)]吗?(PFA游乐场)
我将此行为作为一个例子提交,结果它以“按预期工作”的形式返回。为了找到一种向您解释它的方法,我必须对响应进行一些思考;我认为这可以非常准确和清晰地表达它。我们走 要了解这里发生了什么,让我们自己编写类似于
compactMap
的东西。假设compactMap
做了三件事:
Int?
元素
let marks = ["86", "45", "thiry six", "76"]
let result = marks.map { element -> Int? in
return Int(element)
}.filter { element in
return element != nil
}.map { element in
return element!
}
好的,但在您的示例中,对[Int?]
的转换告诉compactMap
输出Int?
,这意味着它的第一个map
必须生成Int???
let result3 = marks.map { element -> Int?? in
return Int(element) // wrapped in extra Optional!
}.filter { element in
return element != nil
}.map { element in
return element!
}
因此,第一个map
生成双包装选项,即可选(可选(86))
,可选(可选(45))
,可选(无)
,可选(可选(76))
所有这些都不是nil
,因此它们都会通过过滤器,然后都会展开一次,以给出打印出来的结果
回答我报告的Swift专家承认,这有点违反直觉,但这是我们为自动行为付出的代价,在自动行为中,分配到可选的执行自动包装。换句话说,你可以说
let i : Int? = 1
因为1
在您进入作业的过程中被包装在一个可选文件中。您的[Int?]
演员阵容要求进行同样的行为
解决方法是自己明确指定转换的输出类型:
这会阻止编译器对map函数的输出类型得出自己的结论。问题解决了
[您可能还想看看Swift中的on类型推断。]我没有在任何地方使用它。我只是想分析结果。好吧,那看起来像个bug。很容易描述发生了什么:在第二个示例中,我们实际上调用了
map
,而不是compactMap
。但我不知道为什么光是演员就会造成这种情况。我已经向bugs.swift.org提交了这个文件。他们都在幕后调用map
。。。只有一个过滤掉了零,另一个没有,因为它不必..这是一个非常古老的行为;我刚刚在Xcode 9.2中确认了这一点。所以这可能是故意的。但我发现很难证明这一点;当然,它打破了一个人的及物性意识,在这种情况下,b=a;c=b
给出了与c=a
@KirilS不同的结果(c
)。是的,我就是这么想的。它“看到”我们将要分配给一个[Int?]
,所以它对自己说,“哦,你毕竟愿意接受可选的,所以我没有工作要做。”但这仍然不是我所期望的语言的行为方式。好吧,这比我所期望的有趣得多!提供了解释和解决方法。
let result3 = marks.compactMap {element -> Int? in Int(element) }