2013-11-03 24 views
7

我非常喜歡pow**語法,可用於多種語言(如Python)。爲Scala創建`**`強大的操作符?

是否可以在不修改Scala「基本」代碼的情況下將其引入到Scala中?

我嘗試在Int只有一個:

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

(見它沒有按規定IDEone

+7

注意'**'沒有'^'不會有正確的優先級(這就是之所以STDLIB不包括它)。 '4 * 5 ** 3'是'(4 * 5)** 3'而不是'4 *(5 ** 3)'。 – sschaef

+0

Scala可以將其解析方法更改爲非LL(1)語法;例如:看看C++如何處理多個'>''<確定性的> –

回答

11

這個工作對我來說:(問題#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) 
    } 

} 
+1

這非常酷。 –

12

這個答案爲2年後期,仍然FO我希望指出的是,接受的答案不必要地從AnyVal延伸出來。

只有一個小錯誤需要在原始答案中解決。 def **方法只需要一個參數,即指數作爲基礎已經在構造函數中傳遞,而不是在原始代碼中傳遞兩個參數。修復這一點,在去除反引號結果:

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

像預期的那樣看到here其中一期工程。

Scala編譯器會施放一個IntPowerInt如果被調用它的方法是不確定的。這就是爲什麼你不需要從AnyVal擴展。

在幕後,Scala尋找一個隱式類,其構造函數參數類型與所投射對象的類型相同。由於對象只能有一種類型,因此隱式類在其構造函數中不能有多個參數。而且,如果你定義了兩個具有相同構造器類型的隱式類,確保它們的函數具有唯一的簽名,否則Scala不知道要投射哪個類,並且會抱怨含糊不清。

1

有一種方法,使該解決方案有點更通用的使用Numeric類型類:

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

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