例如这个代码:
func trigramSimilarity(to other: Set<String>) -> Double {
let selfTrigram = trigrams()
let total = selfTrigram.union(other)
let common = selfTrigram.intersection(other)
return total.isEmpty ? 0 : Double(common.count) / Double(total.count)
}
我希望编译器转换为
func trigramSimilarity(to other: Set<String>) -> Double {
let selfTrigram = trigrams()
let total = selfTrigram.union(other)
return total.isEmpty ? 0 : Double(selfTrigram.intersection(other).count) / Double(total.count)
}
通过注意到,如果swift 编译器可以让我编写更简单的代码但避免不必要的计算,那么这let common
是不需要的。total.isEmpty
但直接说出来是否更安全呢?
正如您在 Godbolt 输出中所看到的,Sweeper 链接的被无条件调用,如果最终结果为真,
Set.intersection(_:)
则可能会造成浪费。total.isEmpty
您的代码要求
Set.intersection(_:)
无条件调用,因此编译器有义务生成表现得像真的被调用一样的代码。显而易见的方法是调用它。但它也可以变得聪明并跳过调用它,但前提是它可以确保函数没有可观察到的副作用。也就是说,如果没有办法观察它是否被调用。除非它能证明这一点,否则它必须保守并保留调用。在这种情况下,我认为使用明确的
if
/会更清楚else
:编译后的输出确认现在
common
仅当total.isEmpty
结果为假时才进行计算。更好的是,我建议使用提前返回: