function - tag - ¿Cuándo tengo que tratar mis métodos como funciones parcialmente aplicadas en Scala?
the_tags wordpress (3)
En Scala, un método no es una función. El compilador puede convertir un método implícitamente en una función, pero necesita saber qué tipo. Entonces, puede usar _
para convertirlo explícitamente o puede dar algunas indicaciones sobre qué tipo de función usar:
object Whatever {
def meth1(params:Array[Int]): Int = ...
def meth2(params:Array[Int]): Int = ...
}
import Whatever._
val callbacks = Array[ Array[Int] => Int ]( meth1, meth2 )
o:
val callbacks: Array[ Array[Int] => Int ] = Array( meth1, meth2 )
Noté que cuando estoy trabajando con funciones que esperan otras funciones como parámetros, algunas veces puedo hacer esto:
someFunction(firstParam,anotherFunction)
Pero otras veces, el compilador me está dando un error, diciéndome que debería escribir una función como esta, para que pueda tratarla como una función parcialmente aplicada:
someFunction(firstParam,anotherFunction _)
Por ejemplo, si tengo esto:
object Whatever {
def meth1(params:Array[Int]) = ...
def meth2(params:Array[Int]) = ...
}
import Whatever._
val callbacks = Array(meth1 _,meth2 _)
¿Por qué no puedo tener el código como el siguiente?
val callbacks = Array(meth1,meth2)
¿Bajo qué circunstancias el compilador me dirá que agregue _
?
La regla es realmente simple: tiene que escribir _
siempre que el compilador no espere explícitamente un objeto Function
.
Ejemplo en REPL:
scala> def f(i: Int) = i
f: (i: Int)Int
scala> val g = f
<console>:6: error: missing arguments for method f in object $iw;
follow this method with `_'' if you want to treat it as a partially applied function
val g = f
^
scala> val g: Int => Int = f
g: (Int) => Int = <function1>
Además de lo que dijo Jean-Philippe Pellet, puede usar funciones parcialmente aplicadas al escribir clases delegadas:
class ThirdPartyAPI{
def f(a: Int, b: String, c: Int) = ...
// lots of other methods
}
// You want to hide all the unnecessary methods
class APIWrapper(r: ThirdPartyAPI) {
// instead of writing this
def f(a: Int, b: String, c: Int) = r.f(a, b, c)
// you can write this
def f(a: Int, b: String, c: Int) = r.f _
// or even this
def f = r.f _
}
EDIT agregó la parte def f = rf _
.