java interop clojure aot

¿Cómo pasar una colección mecanografiada de clojure a java?



interop aot (3)

Conozco los conceptos básicos de interoperabilidad clojure / java: llamar a java desde clojure y viceversa. Sin embargo, no pude devolver una colección mecanografiada de clojure a java. Estoy tratando de ver algo de esa naturaleza en la List<TypedObject> del código java que está llamando a clojure.

Java Object: public class TypedObject { private OtherType1 _prop1; public OtherType1 getProp1() { return _prop1; } public void setProp1(OtherType1 prop1) { _prop1 = prop1; } } CLojure method: (defn -createListOfTypedObjects "Creates and returns a list of TypedObjects" [input] ;Do work here to create and return list of TypedObjects [typedObj1, typedObj2, typedObj3]) (:gen-class :name some.namespace :methods [createListofTypedObjects[String] ????])

Consideremos que estoy escribiendo una API utilizando clojure, que se distribuirá como un archivo jar, que se utilizará desde Java. Mi pregunta era realmente cómo pasar en lugar de la ???? signos de interrogación anteriores dentro del: Gen-clase para AOT, por lo que un programador escribir un fragmento de código en Java usando mi api, pueden tener la intelisense / la ejecución de código apropiado (es decir: createListofTypedObjects() returns List<TypedObject> ) desde dentro de Eclipse por ejemplo.


Los otros tienen razón al afirmar que Clojure no garantiza los tipos de elementos en las colecciones devueltas, etc. (En realidad, la JVM no garantiza los tipos de elementos en las colecciones, eso es totalmente manejado por javac).

Sin embargo, puedo ver el valor de proporcionar una API a otros programadores de Java que especifica una interfaz que declara que los valores de retorno (o parámetros) están parametrizados de varias maneras; Esto es especialmente atractivo si uno está buscando usar Clojure en un entorno Java existente sin hacer olas.

Esto requiere actualmente un proceso de dos pasos:

  • define una interfaz separada (en Java!) que especifica los tipos parametrizados como quieras
  • defina su espacio de nombres gen-class (o proxy o reify instancia) para que implemente esa interfaz

(Clojure proporciona una forma de definterface que le permitiría evitar la definición de la interfaz Java separada, pero la interfaz definterface , al igual que el resto de Clojure, no permite especificar tipos parametrizados. Tal vez algún día ... :-))

p.ej

public interface IFoo { List<TypedObject> createListOfTypedObjects (); }

y luego su espacio de nombres de clase gen:

(ns your.ns.FooImpl (:gen-class :implements [IFoo])) (defn -createListOfTypedObjects [] [typedObj1, typedObj2, typedObj3])

Cuando sus usuarios crean instancias de FooImpl , por ejemplo, obtendrán la finalización del código que indica que el método devuelve la List<TypedObject> lugar de Object o el tipo de List parámetros.

Si está utilizando herramientas de compilación sanas (por ejemplo, maven , gradle o antemano correctamente configuradas), entonces puede poner la interfaz Java en su proyecto Clojure, y se cuidará la dependencia entre idiomas.


No debe preocuparse por los genéricos (colecciones mecanografiadas) en Clojure. Los genéricos son en realidad solo sugerencias de tipo para el compilador de Java. En un programa Java en ejecución, List<String> es efectivamente lo mismo que List<Object> .

Entonces, por ejemplo, un vector de Clojure que contiene cadenas ya es una List<String> sin necesidad de conversión.


Si está intentando pasar algo como List<String> a un método java, entonces no debe preocuparse por ello. El parámetro de tipo (por ejemplo, String ) solo lo utiliza el compilador javac, por lo que cualquier List funcionará bien en el tiempo de ejecución.

Por otro lado, si está tratando de pasar una matriz de un tipo de objeto en particular (por ejemplo, String[] ), puede usar las diversas funciones de -array :

user=> (make-array String 10) ; an empty String array #<String[] [Ljava.lang.String;@78878c4c> user=> (into-array ["foo" "bar"]) ; array type inferred from first element #<String[] [Ljava.lang.String;@743fbbfc> user=> (into-array Number [1.2 5 7N]) ; explicit type array #<Number[] [Ljava.lang.Number;@7433b121>