Notación Scala infijo

12

¿Es posible llamar a un método usando notación infija?

Por ejemplo, en Haskell, podría escribir la siguiente función:

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

y luego úsalo como:

if 2 `isAFactorOf` 10 ...

Lo que en algunos casos permite un código muy legible. ¿Es posible algo similar a esto en Scala? Busqué "notación Scala infijo", pero ese término parece significar algo diferente en Scala.

Carcigenicate
fuente

Respuestas:

15

A partir de la versión 2.10, Scala introdujo clases implícitas para manejar precisamente este problema.

Esto realizará una conversión implícita de un tipo dado a una clase envuelta, que puede contener sus propios métodos y valores.

En su caso específico, usaría algo como esto:

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

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

Tenga en cuenta que cuando se compila, esto terminará encajonando nuestro valor bruto en a RichInt(2). Puede evitar esto declarando su RichInt como una subclase de AnyVal:

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

Esto no causará el boxeo, pero es más restrictivo que una clase implícita típica. Se puede solamente contener métodos, no valores o estado.

KChaloux
fuente
2
Probablemente debería mencionar que las clases implícitas no pueden ser de nivel superior, por lo que la clase implícita deberá definirse localmente.
Carcigenicate
3

Esencialmente, en Scala no puede llamar a una función de manera infija, pero puede definir un método en un tipo, al que el argumento izquierdo se puede convertir implícitamente. Entonces, para su ejemplo, puede definir una clase que tenga un método isAFactorOf (tomar un Int) e indicar que un Int puede convertirse implícitamente en una instancia de esta clase.

Si observa esta respuesta /programming//a/3119671 a otra pregunta, verá la sintaxis en Scala que funciona de manera equivalente.

eques
fuente
Vale la pena señalar que las nuevas versiones de Scala presentan una construcción explícita para esto, que la respuesta vinculado no trata: implicit class RichInt(i: Int) { def square() = i * i }.
KChaloux