【问题标题】:Scala Numeric init with constant 0Scala Numeric init 常量为 0
【发布时间】:2012-06-22 19:53:54
【问题描述】:

让我有一个名为 MathUtil 的实用程序类。

它看起来像这样。

abstract class MathUtil(T:Numeric){
   def nextNumber(value:T)
   def result():T
}

让我这样子类化它

class SumUtil[T:Numeric] extends MathUtil[T]{
   private var sum:T = 0
   override def nextNumber(value:T){
     sum = sum + value
   }
   override def result():T = sum
}

我的陈述有问题

private var sum:T = 0

现在,我必须初始化总和为 0。我猜想任何数字都有办法表示 0。我对 scala 很陌生。我该如何解决这个问题?

【问题讨论】:

  • 感谢大家的回答。我有一个后续问题。假设我有一个具有 MathUtils 类型的可覆盖成员的类。

标签: scala numeric


【解决方案1】:

Numeric type class instance 有一个 zero 方法可以满足您的需求:

class SumUtil[T: Numeric] extends MathUtil[T] {
   private var sum: T = implicitly[Numeric[T]].zero
   override def nextNumber(value: T) {
     sum = implicitly[Numeric[T]].plus(sum, value)
   }
   override def result(): T = sum
}

请注意,您还需要plus 方法的实例,除非您导入Numeric.Implicits._,在这种情况下您可以使用+。在这种情况下,您还可以通过不使用上下文绑定语法来稍微清理一下代码:

class SumUtil[T](implicit ev: Numeric[T]) extends MathUtil[T] {
   import Numeric.Implicits._
   private var sum: T = ev.zero
   override def nextNumber(value: T) {
     sum = sum + value
   }
   override def result(): T = sum
}

这是完全等价的:上下文绑定版本只是这个隐式参数的语法糖,但如果你需要显式使用这个参数(就像你在这里所做的那样,因为它的zero),我发现编写脱糖版本。

【讨论】:

  • 嘿特拉维斯!很高兴看到你在这里发帖(这是来自奥斯汀的本)。不幸的是,这个数字的东西,IMO,完全是丑陋的。事实证明它也很慢。 IMO 整个 Scala 隐式机制笨拙、脆弱且难以理解,您仍然需要像 @specialized 这样的其他垃圾,这也主要是被破解了。我认为使用 C++ 风格的类专业化可以更好地表达这些东西,这将 just work 每个人都期望的方式,基本上是通过使用 s/int/double 复制实现/ 或其他。
  • @UrbanVagabond:嗨,本!我同意Numeric 是一团糟,我不记得上次在自己的代码中使用它是什么时候了,但我个人认为问题不在于 Scala 实现类型类的方式(我实际上已经成长喜欢)。
【解决方案2】:

我认为需要稍微澄清一下您要完成的工作。从 Scala 文档中,Numeric 类型本身是通用的。我的感觉是你真正想要的是描述一个处理任何 Numeric[T] 而不是 Numeric[_] 的子类的 MathUtil 抽象,这是你的代码当前正在描述的。这是基于该假设的正确实现。

//Define a MathUtil that works on any T
abstract class MathUtil[T] {
    def nextNumber(value: T)
    def result(): T
}

//Define a SumUtil that works on any T that has an available Numeric
//Will search implicit scope, but also allows you to provide an
//implementation if desired.
class SumUtil[T](implicit n: Numeric[T]) extends MathUtil[T] {
    //Use the Numeric to generate the zero correctly.
    private var sum: T = n.zero
    //Use the Numeric to correctly add the sum and value
    override def nextNumber(value: T) = sum = n.plus(sum, value)
    override def result(): T = sum
}

//Test that it works.
val a = new SumUtil[Int]
val b = List(1,2,3)

b map a.nextNumber //Quick and dirty test... returns a meaningless list
println(a.result)  //Does indeed print 6

如果以上内容不能满足您的要求,请澄清您的问题。

【讨论】:

  • 你错了...[T : Numeric] 是上下文绑定的,将扩展为[T](implicit n: Numeric[T]),因此您的代码几乎与 OP 的代码相同,除了n.zero。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-08
  • 1970-01-01
  • 1970-01-01
  • 2016-03-19
  • 1970-01-01
相关资源
最近更新 更多