2011-09-20 6 views
5

Aquí en el trabajo la mayoría de la gente usa Java, mientras estoy trabajando con Scala. Hemos decidido reunir algunas clases comunes en una biblioteca que se escribirá en Java. Ahora quiero añadir un poco de programación pseudo-funcional a la biblioteca, echar un vistazo a los siguientes:manera suave de utilizar la función <A, R> interfaz java de scala?

java:

public interface Func<A, R> { 
    public R f(a A); 
} 

public AClass { 
    public <R> ArrayList<R> myMethod(
          Func<String, R> func 
    ) { 
     // ... 
    } 
} 

uso en Java:

AClass ac = new AClass(); 
ArrayList<String> al = ac.myMethod(
          new Func<String, String> (
           public String f(String s) { 
            return s + "!"; 
           } 
          }) 

Lo anterior no es exactamente salir (más como desalentador en realidad, desde una perspectiva scala). ¿Hay alguna manera de convocar un poco de magia Scala para ser capaz de hacer algo como lo siguiente en Scala:

var ac = new ACLass 
var al = ac.myMethod(str => str + "!")    // alternative 1 
al = ac.myMethod { case: str:String => str + "!" } // alternative 2 

ensucié alrededor con implícitos por un tiempo pero no podía hacer las cosas lo solucionaron = P.

+0

¿Ha intentado crear un adaptador en Scala que tome una lambda y la convierta en una clase interna anónima para que la biblioteca la consuma? No estoy seguro de si logrará que esto funcione con los genéricos en tiempo de compilación ... – Bringer128

+0

Lo hice, pero no lo hice funcionar =) – fickludd

Respuesta

14

Con las conversiones implícitas:

object FuncConversions { 
    implicit def func2function[A,R](fn: (A) => R) = 
    new Func[A,R] { 
     def f(a: A) = fn(a) 
    } 
} 

No se olvide de importar la conversión en su ámbito de aplicación:

import FuncConversions._ 

También puede implementar la conversión opuesta.

+1

Oh mierda, ahora lo entiendo. Estaba intentando ese mismo código pero con 'def f = fn _' en su lugar, que dio:' : 8: error: _ debe seguir el método; no puede seguir func.type'. ¡Gracias! – fickludd

6

Para ampliar la respuesta paradigmática. Aquí es cómo se trata de descubrir lo implícito. Las conversiones implícitas entran en juego cuando los tipos no se controlan. Cuando eso sucede, el compilador buscará una conversión implícita para usar de modo que los tipos coincidan.

Después de la limpieza de su ejemplo un poco, en el REPL, el compilador mostrará:

scala> ac.myMethod((s:String) => s + "!") 
<console>:9: error: type mismatch; 
found : String => java.lang.String 
required: Func[java.lang.String,?] 
       ac.myMethod((s:String) => s + "!") 

Así el compilador te dice que encontró una (String) => (String) pero necesita un Func[String, ?]. Por lo tanto, desea proporcionar una conversión implícita entre el tipo encontrado y el tipo requerido tipo. Por lo que la firma debe ser algo como:

implicit def fun2Func(fun: (String) => String): Func[String,String] 

A continuación, el siguiente paso es darse cuenta de que la conversión implícita se puede generalizar con los tipos A y R.

En una nota, me pregunto si había se mejor al reutilizar algo del estante como http://code.google.com/p/guava-libraries/.

+0

+1 por usar guayaba en lugar de 'Func' de cosecha propia.Algún día se convertirán en parte de JDK :) –

+0

Los consejos válidos se basan en que omito mi intento de implementación. guayaba es definitivamente una buena opción! Lo investigaré cuando tenga más tiempo para gastar en la biblioteca. – fickludd

3

No sé exactamente, pero quizás funcional Java http://functionaljava.org/ podría ayudarlo a usted y sus colegas. ¿Qué funciones exactamente intentas reunir en tu lib 'pseudo-fp'?

+0

Nuestra biblioteca no se centra en la programación funcional, simplemente necesitaba pasar funciones como argumentos mientras hacía algunas cosas de interacción con la base de datos, para poder limpiar los recursos antes de volver. Con java como es, creo que la programación funcional será mínima en la biblioteca. – fickludd

Cuestiones relacionadas