为 Scala 创建“**”幂运算符?

Posted

技术标签:

【中文标题】为 Scala 创建“**”幂运算符?【英文标题】:Creating `**` power operator for Scala? 【发布时间】:2013-11-13 22:55:13 【问题描述】:

我非常喜欢pow** 语法,它支持多种语言(例如Python)。

是否可以在不修改 Scala 'base' 代码的情况下将其引入 Scala 中?

我对@9​​87654324@的尝试只有一个:

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

(在IDEone 上看到它失败了)

【问题讨论】:

请注意,**^ 都没有正确的优先级(这就是 stdlib 不包含它的原因)。 4*5**3(4*5)**3 而不是 4*(5**3) Scala 可以将其解析方法更改为非 LL(1) 语法;例如:看看 C++ 如何确定性地处理多个>< 【参考方案1】:

这对我有用:(问题#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)
  


【讨论】:

【参考方案2】:

这个答案晚了 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 将不知道要转换到哪个类并会抱怨歧义。

【讨论】:

"Scala 编译器只有在调用 Int 的方法未定义时才会将 Int 转换为 PowerInt。这就是您不需要从 AnyVal 扩展的原因。"扩展AnyVal 的原因是为了避免实际创建PowerInt 对象。【参考方案3】:

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

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

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

【讨论】:

【参考方案4】:

这是我使用递归的解决方案(所以我不需要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
      

【讨论】:

这不适用于负数或十进制数

以上是关于为 Scala 创建“**”幂运算符?的主要内容,如果未能解决你的问题,请参考以下文章

Scala 的 '::' 运算符,它是如何工作的?

幂运算

矩阵的幂运算

python3怎么取幂

LuoguP1226 模板快速幂||取余运算

Scala 自定义运算符(示例 abs)