¿Cuál es la forma más sencilla de implementar una función parcial de Scala en Java?
-
11-12-2019 - |
Pregunta
Para lograr interoperabilidad, necesito pasar una función parcial de Scala desde el código Java.Para Function (Function1, etc.), existe AbstractFunction que puedo subclasificar con un tipo anónimo, pero ¿cuál sería la forma más sencilla de hacer lo mismo para PartialFunction?
En este caso, me encantaría que fuera una función "completa" en Java, que apareciera definida para todos los valores, pero escrita como PartialFunction.
Solución
Si puede usar Twitter Util Library, tiene una clase específicamente para esto: http://twitter.github.com/util/util-core/target/site/doc/main/api/com/twitter/util/function.html que es básicamente la misma solución que abstractpartialfunction.
Otros consejos
Lo que haría aquí es proporcionar una interfaz en Java, en alguna biblioteca común (que no sea compatible con Scala):
//this is Java - in the Java lib
abstract class PartialTransformer<I, O> {
abstract public boolean isDefinedAt(I i);
public O transform(I i) {
if (isDefinedAt(i)) {
return transform0(i);
}
return null;
}
abstract protected O transform0(I i);
}
Entonces, en escala (es decir.una biblioteca Scala dependiente de la biblioteca Java anterior), convertir una implementación de esto en una PartialFunction
:
//this is scala - in the scala lib
object MyPartialFunctions {
def fromPartialTransformer[I, O](t: PartialTransformer[I, O]) = new PartialFunction[I, O] {
def isDefinedAt(i: I) = t isDefinedAt i
def apply(i: I) = {
val r = t transform i
if (r eq null) throw new MatchError
else r
}
}
}
Entonces tu código Java puede hacer esto:
//This is Java - in your client code
MyPartialFunctions$.MODULE$.fromPartialTransformer(new PartialTransformer<Integer, String>() {
@Override public boolean isDefinedAt(Integer i) { /* */ }
@Override protected String transform0(Integer i) { /* */ }
}
Si no te gusta el MyPartialFunctions$.MODULE$
sintaxis, es posible en la biblioteca scala, a clase java que te oculta esto:
//This is Java - in the scala-lib
public class ScalaUtils {
public <I, O> scala.PartialFunction<I, O> toPartialFunction(PartialTransformer<I, O> t) {
MyPartialFunctions$.MODULE$.fromPartialTransformer(t);
}
}
Entonces su sitio de llamadas se ve así:
//This is Java - in your client code
ScalaUtils.toPartialFunction(new PartialTransformer<Integer, String>() {
@Override public boolean isDefinedAt(Integer i) { /* */ }
@Override protected String transform0(Integer i) { /* */ }
}
¡Esto implica, ejem, algunos niveles de direccionamiento indirecto!
Como complemento de la respuesta de Chris, en Scala 2.10 puede usar esto: http://www.scala-lang.org/archives/downsloads/distrib/files/nightly/docs/library/scala/runtime/abstractpartialfunction.html