2013-11-03 10 views
7

pow**の構文が好きで、多くの言語(Pythonなど)で利用できます。Scala用の `**`パワー演算子の作成?

これをScalaの 'base'コードを変更せずに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はダブルスで定義され、anyvalの延長問題#2 ) (もmethodNameの中で、これらのバッククォートを持つにはポイントがありません?)

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

この答えはFOまだ、2年遅れていますr他の人の利益私は、受け入れられた答えがAnyValから不必要に延びることを指摘したいと思います。

元の回答で修正する必要のある小さなバグがあります。 def **メソッドは、ただ1つのパラメータ、すなわちベースが既にコンストラクタで渡され、元のコードのように2ではない指数である必要があります。それを固定し、中にバッククォートの結果を削除:hereを見られるように、期待通りに動作します

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

。その上で呼び出されるメソッドが定義されていない場合

ScalaのコンパイラはPowerIntのみIntをキャストします。そのため、AnyValから拡張する必要はありません。

Scalaは背後に、コンストラクタ引数の型がキャストされているオブジェクトの型と同じである暗黙のクラスを探します。オブジェクトは1つの型しか持てないので、暗黙のクラスはコンストラクタに複数の引数を持つことはできません。さらに、同じコンストラクタ型を持つ2つの暗黙のクラスを定義する場合、それらの関数が一意のシグネチャを持つことを確認してください。そうでない場合、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()) 
}