简体   繁体   English

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

[英]Creating `**` power operator for Scala?

I quite like the ** syntax for pow , available in many languages (such as Python). 我非常喜欢pow**语法,可用于许多语言(例如Python)。

Is it possible to introduce this into Scala, without modifying the Scala 'base' code? 是否可以将其引入Scala,而无需修改Scala“基础”代码?

My attempt at an Int only one: 我在Int只尝试一次:

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

(see it failing on IDEone ) (看到它在IDEone失败

this works for me: (problem#1 pow is defined on doubles, problem#2 extending anyval) (also there is no point in having those backticks in the methodname?) 这对我有用:(问题#1 pow在双打中定义,问题#2扩展为anyval)(也没有意义在方法名中有这些反引号?)

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)
  }

}

This answer is 2 years late, still for the benefit of others I'd like to point out that the accepted answer unnecessarily extends from AnyVal. 这个答案迟了2年,仍然为了其他人的利益,我想指出所接受的答案不必要地延伸到AnyVal。

There is just a minor bug that needs to be fixed in the original answer. 只有一个小错误需要在原始答案中修复。 The def ** method needs only one parameter, ie the exponent as the base is already passed in the constructor and not two as in the original code. def **方法只需要一个参数,即指数作为基础已经在构造函数中传递,而不是原始代码中的两个。 Fixing that and removing the backticks results in: 修复并删除反引号会导致:

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

Which works as expected as seen here . 其作品如预期看到这里

Scala compiler will cast an Int to a PowerInt only if the method that is called on it is undefined. 只有在未定义调用的方法时,Scala编译器才会将Int PowerInt转换为PowerInt That's why you don't need to extend from AnyVal. 这就是你不需要从AnyVal扩展的原因。

Behind the scenes, Scala looks for an implicit class whose constructor argument type is the same as the type of the object that is cast. 在幕后,Scala查找一个隐式类,其构造函数参数类型与转换对象的类型相同。 Since the object can have only one type, implicit classes cannot have more than one argument in their constructor. 由于对象只能有一个类型,因此隐式类在构造函数中不能有多个参数。 Moreover, if you define two implicit classes with the same constructor type, make sure their functions have unique signatures otherwise Scala wouldn't know which class to cast to and will complain about the ambiguity. 此外,如果您使用相同的构造函数类型定义两个隐式类,请确保它们的函数具有唯一的签名,否则Scala将不知道要转换到哪个类并且会抱怨歧义。

There is a way to make the solution a little bit more generic using Numeric typeclass: 有一种方法可以使用Numeric类型类使解决方案更通用:

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

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

This is my solution using recursion (so I don't need import scala.Math.pow ): 这是我使用递归的解决方案(所以我不需要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
    }  
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM