Scala 应用于Int和Long的泛型隐式类
我想通过添加一些助手方法为Scala中的自然数创建一个“皮条客我的类型” 我的第一次尝试是为Scala 应用于Int和Long的泛型隐式类,scala,Scala,我想通过添加一些助手方法为Scala中的自然数创建一个“皮条客我的类型” 我的第一次尝试是为Int创建一个,为Long创建一个(以后可能还会为BigInt创建一个) 当然,代码完全相同,不太干,而且“感觉”不对 所以我的问题是-什么是(惯用的)Scala方法可以同时长时间、Int和BigInt执行此操作? p、 这是我到目前为止所尝试的,它有点有效,但我很确定它不是惯用的,并且有很多问题 下面是读了一点关于“类型类”(我仍然不完全认为我100%理解)的结果(如果你的眼睛受伤了,请原谅,我对Sc
Int
创建一个,为Long
创建一个(以后可能还会为BigInt
创建一个)
当然,代码完全相同,不太干,而且“感觉”不对
所以我的问题是-什么是(惯用的)Scala方法可以同时长时间、Int和BigInt执行此操作?
p、 这是我到目前为止所尝试的,它有点有效,但我很确定它不是惯用的,并且有很多问题 下面是读了一点关于“类型类”(我仍然不完全认为我100%理解)的结果(如果你的眼睛受伤了,请原谅,我对Scala比较陌生)
(我添加了对非Int的“支持”,只要它看起来不太难)您所拥有的看起来非常接近。几点意见: 您想要的类型类是
整数
,而不是数值
不要将上下文绑定为[A:Integral]
,而是在构造函数上放置一个隐式参数,以便可以从该对象导入mkNumericOps
:
implicit class SuperNumber[A](i: A)(implicit integral: Integral[A]) {
import integral._
请记住,与原语相比,任何带有
数值的都会非常慢。有关如何快速执行此操作,请参见spire。这可不是什么小事。(谷歌scala spire。)谢谢,我想在这种情况下,DRY可以离开窗口,我可以简单地拥有一个trait SuperNum
,它有squared:Numeric
等,并用squared:Long
覆盖它,等很久吗?谢谢!这种方法有运行时性能价格标签吗?是的,据我所知。因为要计算4.squared
,它必须将int
框为int
,将其包装在一个SuperNumber
(有两个字段)中,然后用IntegralOps
再次包装以进行乘法。这是三个对象实例化。现在,在真正的JVM上,这样做的实际成本是多少?我不能说(永远不要在没有基准的情况下推测性能…)
implicit class SuperNumber[A : Numeric](i: A) {
import Numeric.Implicits._
def squared: A = i * i
def pow(m: Int) = math.pow(i.toDouble(),m)
def **(m: Int) = pow(m)
def sqrt = math.sqrt(i.toDouble())
def isEven = dividesBy(2)
def isOdd = !isEven
def dividesBy(m:Int) = {
i match {
case n @ (_:Int | _:Long) => n.toLong() % m == 0
case other => {
val asDouble = other.toDouble()
val asLong = other.toLong()
if (asDouble == asLong) {
asLong % m == 0
} else {
false
}
}
}
}
}
implicit class SuperNumber[A](i: A)(implicit integral: Integral[A]) {
import integral._