2013-11-03 7 views
7

Ich mag die ** Syntax für pow, verfügbar in vielen Sprachen (wie Python).Erstellen "**" Power-Operator für Scala?

Ist es möglich, dies in Scala einzuführen, ohne den Basiscode von Scala zu ändern?

Mein Versuch einer Int nur eins:

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

(siehe auf IDEone Versagen)

+7

Beachten Sie, dass '**' weder '^' das Recht Vorrang nicht haben (das ist der Grund, warum die stdlib enthält es nicht). '4 * 5 ** 3' ist' (4 * 5) ** 3' und nicht '4 * (5 ** 3)'. – sschaef

+0

Scala konnte ihre Analysemethoden in eine nicht LL (1) Grammatik ändern; z. B .: wie C++ mehrere '>' <'deterministisch behandelt –

Antwort

11

dies funktioniert für mich: (Problem # 1 pow auf Doppelzimmer, Problem # 2 erstreckt anyval definiert) (es gibt auch jene Backticks in dem Methodennamen?) kein Punkt

in mit
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

Das ist ziemlich cool. –

12

Diese Antwort 2 Jahre zu spät ist, noch fo Zum Nutzen anderer Ich möchte darauf hinweisen, dass die akzeptierte Antwort unnötigerweise von AnyVal ausgeht.

Es gibt nur einen kleinen Fehler, der in der ursprünglichen Antwort behoben werden muss. Die Methode benötigt nur einen Parameter, d. H. Der Exponent als Basis wird bereits im Konstruktor übergeben und nicht zwei wie im ursprünglichen Code. Festsetzung, dass und das Entfernen der Backticks Ergebnisse in:

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

Welche wie erwartet funktioniert wie here gesehen.

Scala Compiler wirft eine Int ein PowerIntnur wenn die Methode, die auf sie genannt wird nicht definiert ist. Deshalb müssen Sie nicht von AnyVal erweitern.

Hinter den Kulissen sucht Scala nach einer impliziten Klasse, deren Konstruktorargumenttyp mit dem Typ des Objekts übereinstimmt, das umgewandelt wird. Da das Objekt nur einen Typ haben kann, dürfen implizite Klassen nicht mehr als ein Argument in ihrem Konstruktor haben. Wenn Sie zwei implizite Klassen mit demselben Konstruktortyp definieren, stellen Sie außerdem sicher, dass ihre Funktionen eindeutige Signaturen haben, sonst würde Scala nicht wissen, an welche Klasse gewirkt werden soll und wird sich über die Ambiguität beschweren.

1

Es gibt einen Weg, um die Lösung ein wenig mehr Generika mit Numeric typeclass zu machen:

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

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