Scala-Infix-Notation

12

Ist es möglich, eine Methode mit Infix-Notation aufzurufen?

In Haskell könnte ich beispielsweise die folgende Funktion schreiben:

x `isAFactorOf` y = x % y == 0

und dann benutze es wie:

if 2 `isAFactorOf` 10 ...

Dies ermöglicht in einigen Fällen einen gut lesbaren Code. Ist in Scala etwas Ähnliches möglich? Ich habe nach "Scala-Infix-Notation" gesucht, aber dieser Begriff scheint in Scala etwas anderes zu bedeuten.

Carcigenicate
quelle

Antworten:

15

Ab Version 2.10 führte Scala implizite Klassen ein, um genau dieses Problem zu lösen.

Dadurch wird eine implizite Konvertierung eines bestimmten Typs in eine umschlossene Klasse durchgeführt, die Ihre eigenen Methoden und Werte enthalten kann.

In Ihrem speziellen Fall würden Sie Folgendes verwenden:

implicit class RichInt(x: Int) {
  def isAFactorOf(y: Int) = x % y == 0
}

2.isAFactorOf(10)
// or, without dot-syntax
2 isAFactorOf 10

Beachten Sie, dass beim Kompilieren unser Rohwert in a gepackt wird RichInt(2). Sie können dies umgehen, indem Sie Ihr RichInt als Unterklasse von deklarieren AnyVal:

implicit class RichInt(val x: Int) extends AnyVal { ... }

Dies verursacht kein Boxen, ist jedoch restriktiver als eine typische implizite Klasse. Es kann nur Methoden enthalten, keine Werte oder Zustände.

KChaloux
quelle
2
Sie sollten wahrscheinlich erwähnen, dass implizite Klassen nicht die oberste Ebene sein können, daher muss die implizite Klasse lokal definiert werden.
Carcigenicate
3

Im Wesentlichen können Sie in Scala eine Funktion nicht auf Infix-Weise aufrufen, sondern Sie können eine Methode für einen Typ definieren, in die das linke Argument implizit konvertiert werden kann. In Ihrem Beispiel können Sie also eine Klasse mit der Methode isAFactorOf (unter Verwendung eines Int) definieren und angeben, dass ein Int implizit in eine Instanz dieser Klasse konvertiert werden kann.

Wenn Sie sich diese Antwort /programming//a/3119671 auf eine andere Frage ansehen , sehen Sie die Syntax in Scala, die gleichwertig funktioniert.

eques
quelle
Es sei darauf hingewiesen, dass neue Versionen von Scala explizit ein Konstrukt dafür haben, das in der verknüpften Antwort nicht behandelt wird : implicit class RichInt(i: Int) { def square() = i * i }.
KChaloux