Scala infix notation

12

Est-il possible d'appeler une méthode en utilisant la notation infixe?

Par exemple, dans Haskell, je pourrais écrire la fonction suivante:

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

puis l'utiliser comme:

if 2 `isAFactorOf` 10 ...

Ce qui dans certains cas permet un code très lisible. Est-ce que quelque chose de similaire est possible à Scala? J'ai cherché "notation infala Scala", mais ce terme semble signifier quelque chose de différent dans Scala.

Carcigenicate
la source

Réponses:

15

À partir de la version 2.10, Scala a introduit des classes implicites pour gérer précisément ce problème.

Cela effectuera une conversion implicite sur un type donné en une classe encapsulée, qui peut contenir vos propres méthodes et valeurs.

Dans votre cas spécifique, vous utiliseriez quelque chose comme ceci:

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

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

Notez que lors de la compilation, cela finira par boxer notre valeur brute dans un fichier RichInt(2). Vous pouvez contourner cela en déclarant votre RichInt comme une sous-classe de AnyVal:

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

Cela ne causera pas de boxe, mais c'est plus restrictif qu'une classe implicite typique. Il ne peut contenir que des méthodes, pas des valeurs ou des états.

KChaloux
la source
2
Vous devez probablement mentionner que les classes implicites ne peuvent pas être de niveau supérieur, donc la classe implicite devra être définie localement.
Carcigenicate
3

Essentiellement, dans Scala, vous ne pouvez pas appeler une fonction de manière infixe, mais vous pouvez définir une méthode sur un type, dans lequel l'argument de gauche peut être converti implicitement. Donc pour votre exemple, vous pouvez définir une classe qui a une méthode isAFactorOf (prendre un Int) et indiquer qu'un Int peut être implicitement converti en une instance de cette classe.

Si vous regardez cette réponse /programming//a/3119671 à une autre question, vous verrez la syntaxe dans Scala qui fonctionne de manière équivalente.

eques
la source
Il est intéressant de souligner que les nouvelles versions de Scala ont une construction explicite pour ce qui la réponse liée ne traite pas: implicit class RichInt(i: Int) { def square() = i * i }.
KChaloux