How to create multiple Java member variables using the Clojure gen-class

This answer to a very old question about Clojure -Java interop explains how to use the gen-class with the keywords :state and :init to create one open instance variable available from Java. This is enough if you only need one piece of data available for Java classes, or if you need Java classes to use access functions that read, for example, a map stored in a state variable. This method also allows you to change data, for example. keeping atom in a state variable.

What if I want to create more than one instance variable that is directly readable in a Java class? Is it possible? For example, I can compile the following files and execute the Bar class and see a printout of the value 42 from foo.bar .

Foo.clj:

 (ns students.Foo (:gen-class :name students.Foo :state bar ; :state baz :init init)) (defn -init [] [[] 42]) 

Bar.java:

 package students; public class Bar { public static void main(String[] args) { Foo foo = new Foo(); System.out.println(foo.bar); // System.out.println(foo.baz); } } 

If I uncomment the baz lines, Bar.java will not compile - the compiler accidentally creates either Bar or baz as a state variable for Foo , so only one of them is available for Bar . And in any case, I don’t see how to initialize both Bar and baz using the init function.

+6
source share
1 answer

The gen-class macro does not support the definition of more than one open field. Instead, you should use the defrecord macro or the deftype macro.

 (defrecord Foo [bar baz]) 

Unfortunately, the defrecord macro and the defrecord macro deftype not deftype way to define their constructors. So, when initializing multiple instance variables is mandatory, there is no shame in writing a Java class in Java.

+2
source

Source: https://habr.com/ru/post/986374/


All Articles