How to use a Clojure proxy to create a Java class?

I want to create an object with properties and methods in Clojure, I read that the gen class and proxy server can do the required work, but its implementation is very confusing for me.

I want to use a proxy server to avoid the AOT compilation steps, I read about it, and although I better learn how to use simpler ones

Here is what I want to do in Clojure

Java Code:

public class MyClass { public float myFloat; MyClass( float _myFloat ) { myFloat = _myFloat } public void showNumber() { println( myFloat ); } } 

I am trying to translate this code to Clojure using proxys, any help would be greatly appreciated


UPDATE:

Deftype seems to be more suitable for my purposes, but I'm still afraid of its implementation

Here is my Clojure code:

 (deftype Particle [xy] Object (render [this] (no-stroke) (fill 200 30 180) (ellipse xy 200 200))) 

I need to specify a protocol, which I'm not sure which one to use, so I use Object, as I try to create an object of type java class, but I get the folloiwng error message:

Unable to define method not in interfaces: render

I use a pen, which is the processing port for Clojure, if that helps


UPDATE 2:

OK I manage to get the defprotocol and deftype working command, but there is one more thing that I need to work through, and that I need to add member variables or properties to my class, here is my Clojure code:

 (defprotocol ParticleProtocol (update [this]) (render [this])) (deftype Particle [position] ParticleProtocol (update [this]) (render [this] (no-stroke) (fill 200 30 180) (ellipse (.x position) (.y position) 20 20))) 

To this object I would like to add a couple of variables, such as radius among others, any ideas?

+4
source share
2 answers

I agree that deftype (or perhaps defrecord ) is better than proxy to do this in Clojure, but at the end of my comments we’ll cover all the possibilities.

For your question after UPDATE 2.

You can add “properties” to entries by specifying them in an arglist:

 (deftype Particle [position radius prop3 prop4] ... ) 

Remember that types in Clojure are immutable, so after creating an object there is no concept of setting properties. If some of the properties are optional, it is recommended that you use the best factory methods, for example:

 (defn make-particle ([position] (Particle. position nil nil nil)) ([position radius] (Particle. position radius nil nil)) ;; etc. add more here as needed ) 

You might want to consider completely removing types and simply using maps that have any “properties / fields” inside them that you need. Types are useful when you need to implement abstractions. For your ParticleProtocol - what is the value it provides? Protocols are designed to provide polymorphism, so you will have several implementations of this protocol?

Chas Emerick completed a detailed description of how to choose a data type in Clojure that can help you: http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form / p>


[Update showing an example implementation of a map] :

To create a map with a “property” and get this property, you would do:

 (def mymap {:myfloat 3.1415926}) (println "myfloat has value:" (:myfloat mymap)) 

To provide additional functions, such as a "rendering" function, simply create fn, which accepts a map with the necessary keys:

 ;; the details are bogus, just showing the syntax (defn render [m] (no-stroke) (fill (:radius m) (:position m)) (do-something-else (:position m))) 

For your update , if you want to update the values ​​in the particle map, you need to create a new map, not update the existing one.

 (def myparticle {:position 100 :radius 25}) (defn change-pos [particle-map new-pos] (assoc-in particle-map [:position] new-pos)) (let [new-particle (change-pos myparticle 300)] (println new-particle)) ;; prints out {:position 300 :radius 25} ;; orig myparticle still has value {:position 100 :radius 25} ;; or do it directly (println (assoc myparticle :position 300)) ;; prints out {:position 300 :radius 25} 
+3
source

You can add “variables” next to position , for example:

 (deftype Particle [position radius] ... ) 

position and radius are not really variables, they are more like final attributes. If you need to “change” them, you must store atoms in them, for example:

 (Particle. (atom (Position. 3 4)) (atom 5.0)) 

But you should heed the advice of @ m0skit0 to stop thinking about objects and classes and start thinking about functions and immutable data structures.

+1
source

All Articles