This article显示:??
非常耗时,测试发现它是真的。所以我想优化它:
#if DEBUG
public func ?? <T>(left: T?, right: T) -> T {
guard let value = left else {
return right
}
return value
}
#endif
但是
string = string ?? ""
错误:Ambiguous use of operator '??'
答案 0 :(得分:0)
如果我重载??
,我就无法使用<T>
...
,然后强>
#if DEBUG
public func ?? (left: Any?, right: Any) -> Any {
guard let value = left else {
return right
}
return value
}
#endif
确定!
但是我无法获得返回值的类型......
答案 1 :(得分:0)
您链接到的文章未描述nil
合并运算符“耗时”的方式,但说明了两个nil
合并的复合表达式的简单事实与我们将这个复合表达式分解为更小的部分相比,运算符调用以及其他求值具有明显更长的构建时间,特别是如果前者在某个时刻包含惰性求值(例如,对于{的rhs的评估就是这种情况) {1}}运营商)。通过分解复杂的表达式,我们帮助编译器;众所周知,Swift在编译复杂的复合语句时遇到一些困难,所以这是预料之中的。但是,这应该通常不会影响运行时性能,因为您为发布模式构建了实现。
通过在调试期间使用??
的非惰性评估重载??
运算符的实现,同时仍使用长复合语句不应完全兑换问题在前一节中描述。如果编译时间确实是一个问题,请使用与文章作者相同的方法;将复杂的表达式分解为几个较小的表达式,这样就可以自己完成编译器的一些工作。重构的唯一目的是减少编译时间(我们可能认为这是编译器的工作,而不是我们)可能会令人沮丧,但这是我们(目前)在使用Swift时必须要考虑的问题。参见例如以下优秀文章介绍了Swift编译器的长/复表达问题:
W.r.t。模糊性错误:作为参考,可以找到lhs
coelescing运算符的正式实现here:
nil
我们可能会注意到它与您自己的通用实现具有相同的特异性(比较签名!),这意味着可能会出现歧义错误。例如,与以下相比:
@_transparent
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T)
rethrows -> T {
switch optional {
case .some(let value):
return value
case .none:
return try defaultValue()
}
}
当您在答案中实施// due to the '@autoclosure', these two have the
// same precedecence/specificity in the overload
// resolution of 'foo(_:)'
func foo<T>(_ obj: T) {}
func foo<T>(_ closure: @autoclosure () -> T) {}
foo("foo") // ERROR at line 9, col 1: ambiguous use of 'foo'
重载时,键入??
,此实现变得比通用实现更具体,这意味着它将优先于{{的重载决策1}}。使用Any
就是这样的背景,然而,通常是一个坏主意,试图模仿动态类型,而不是依赖于Swift着名的静态类型。