为Scala创建`**`power运算符?

时间:2013-11-03 01:11:30

标签: scala operators operator-overloading scala-2.10 pow

我非常喜欢**的{​​{1}}语法,可用于多种语言(例如Python)。

是否可以将其引入Scala,而无需修改Scala'base'代码?

我尝试pow只有一个:

Int

(见IDEone上的失败)

4 个答案:

答案 0 :(得分:14)

这适合我:(问题#1 pow定义在双打,问题#2扩展任何) (也没有必要在方法名中使用这些反引号?)

import scala.math.pow

object RichIntt {

  implicit class PowerInt(val i:Double) extends AnyVal {
    def ** (exp:Double):Double = pow(i,exp)
  }

  def main(args:Array[String])
  {
    println(5**6)
  }

}

答案 1 :(得分:14)

这个答案迟了2年,仍然是为了别人的利益,我想指出所接受的答案不必要地延伸到AnyVal。

在原始答案中只需要修复一个小错误。 def **方法只需要一个参数,即指数,因为基础已在构造函数中传递,而不是原始代码中的两个。修复并删除反引号会导致:

import scala.math.pow
implicit class PowerInt(i: Int) {
    def ** (b: Int): Int = pow(i, b).intValue
}

其效果与预期的here一致。

如果在其上调用的方法未定义,则Scala编译器会将Int强制转换为PowerInt 。这就是为什么你不需要从AnyVal扩展的原因。

在幕后,Scala会查找一个隐式类,其构造函数参数类型与转换对象的类型相同。由于对象只能有一个类型,因此隐式类在构造函数中不能有多个参数。此外,如果您使用相同的构造函数类型定义两个隐式类,请确保它们的函数具有唯一的签名,否则Scala将不知道要转换到哪个类并且会抱怨歧义。

答案 2 :(得分:3)

有一种方法可以使用Numeric类型类使解决方案更加通用:

implicit class PowerOp[T: Numeric](value: T) {
    import Numeric.Implicits._
    import scala.math.pow

    def **(power: T): Double = pow(value.toDouble(), power.toDouble())
}

答案 3 :(得分:0)

这是我使用递归的解决方案(因此,我不需要import scala.Math.pow):

object RichInt {
    implicit class PowerInt(val base:Double) {
        def ** (pow:Double):Double = if (pow==0) 1 else base*(base**(pow-1))
    }

    def main(args:Array[String]){
        println(2.0**3.0) //8.0
        println(2.0**0.0) //1.0
    }  
}