【发布时间】:2017-01-19 09:56:43
【问题描述】:
让我们看看下面的代码sn-p:
func / <T>(lhs: T?,rhs: T?) throws -> T? {
switch (lhs,rhs) {
case let (l?,r?):
return try l/r
default:
return nil
}
}
let x : Double? = 2
let y : Double? = 2
let z = try! x/y
我创建了一个需要两个可选参数的通用函数。如果我运行此代码,它会导致无限循环,因为 try l/r 使用 func / <T>(lhs: T?,rhs: T?) 来划分值。谁能解释为什么将两个非可选的 double 值相除会导致对我编写的方法的函数调用,而不是 Double 的默认 / 运算符定义?
如果我通过一个需要该类的静态 / 运算符的扩展来扩展 Double,那么一切都会像魅力一样工作:
protocol Dividable {
static func /(lhs: Self, rhs: Self) -> Self
}
extension Double: Dividable {}
func / <T:Dividable>(lhs: T?,rhs: T?) throws -> T? {
switch (lhs,rhs) {
case let (l?,r?):
return l/r
default:
return nil
}
}
let x : Double? = 2
let y : Double? = 2
let z = try! x/y
【问题讨论】:
-
由于您的 return 语句中的
try,它可能会导致递归,因为/的内置运算符不会抛出。此外,看起来您的操作员也不会抛出,因此将其标记为throws并没有真正的区别,因为它实际上不会抛出。 -
@xoudiniI 可能只是指出上面赞成的评论中推测的原因不正确:您可以使用
try标记调用非抛出函数(如果您这样做,将提示警告),但这与调用的重载解决方案无关。l/r未能找到 OP 打算使用的重载的原因在下面的答案中进行了介绍。然而,上面评论的第二部分是相关的(为什么扔?)。 -
我是这么想的:将两个 Double 相除可能会导致异常(除以 0),所以我需要用 try 标记 l/r。所以该函数的调用者知道它可能会失败..
-
但正如约瑟夫所说:分母为0时除法会崩溃,不会抛出错误。所以我基本上不确定。
-
@dfri 事实上,我评论的第一部分只是猜测。感谢您的详尽回答——您学到的越多。
标签: swift