【发布时间】:2015-06-11 02:29:29
【问题描述】:
我想在 Scala 中实现一个函数,计算两个数字序列的点积,如下所示
val x = Seq(1,2,3.0)
val y = Seq(4,5,6)
val z = (for (a <- x; b <- y) yield a*b).sum
scala> z : Double = 90.0
val x = Seq(1,2,3)
val y = Seq(4,5,6)
val z = (for (a <- x; b <- y) yield a*b).sum
scala> z : Int = 90
请注意,如果两个序列的类型不同,则结果为 Double。如果两个序列属于同一类型(例如 Int),则结果为 Int。
我想出了两个替代方案,但都不符合上面定义的要求。
备选方案#1:
def dotProduct[T: Numeric](x: Seq[T], y: Seq[T]): T = (for (a <- x; b <- y) yield implicitly[Numeric[T]].times(a, b)).sum
这会返回与输入相同类型的结果,但不能采用两种不同的类型。
备选方案#2:
def dotProduct[A, B](x: Seq[A], y: Seq[B])(implicit nx: Numeric[A], ny: Numeric[B]) = (for (a <- x; b <- y) yield nx.toDouble(a)*ny.toDouble(b)).sum
这适用于所有数字序列。然而,它总是返回一个 Double,即使这两个序列是 Int 类型。
非常感谢任何建议。
附言我上面实现的功能不是“点积”,而只是两个序列的乘积之和。感谢丹尼尔指出这一点。
备选方案#3(略好于备选方案#1 和#2):
def sumProduct[T, A <% T, B <% T](x: Seq[A], y: Seq[B])(implicit num: Numeric[T]) = (for (a <- x; b <- y) yield num.times(a,b)).sum
sumProduct(Seq(1,2,3), Seq(4,5,6)) //> res0: Int = 90
sumProduct(Seq(1,2,3.0), Seq(4,5,6)) //> res1: Double = 90.0
sumProduct(Seq(1,2,3), Seq(4,5,6.0)) // Fails!!!
不幸的是,在 Scala 2.10 中,视图绑定功能(例如“
【问题讨论】:
-
你总是希望它返回 Int 吗?
-
不,他想返回适合这两种类型的最少通用类型