There is a standard function clojure.core/bean converting POJO to map:
class MyPojo{
public String getFirst(){ return "abc"; }
public int getSecond(){ return 15; }
}
IFn bean = Clojure.var("clojure.core", "bean")
var result = bean.invoke(new MyPojo())
// result => {:first = abc, :second = 15}
For Java 17 record classes this function would not work, because records do not follow POJO convention "get***" for properties.
Is there Clojure support for Java 17 record instances in the same manner?
Java 16 introduces Class.getRecordComponents. So given an instance of a record, you can look up the record's class, and from there its record components. Each record component has a name and a getter Method, which you can use to look up the value of that component. You can put these pieces together to build an analogue of bean.
(defn record->map [r]
(into {} (for [^java.lang.reflect.RecordComponent c (seq (.getRecordComponents (class r)))]
[(keyword (.getName c))
(.invoke (.getAccessor c) r nil)])))
Related
Hi Currently I am using java.data (https://github.com/clojure/java.data) to convert java pojos to clojure compatible types.
It does not work for nested objects.
For ex:
class Abc {
Map<String, Def> someMap;
}
Class Def {
String b;
}
If I pass sample instance of Abc to java.data, I get the output as:
{
:someMap {
"keyString" #object[com.sample.Def 0xb33584d "com.sample.Def#b33584d"]
}
}
But I want the output as:
{
:someMap {
"keyString" {
"b" "value"
}
}
}
How can I fix this?
I tried clojure.core bean (https://clojuredocs.org/clojure.core/bean) and it dint seem to work as well.
Thank you in advance.
In order for this to work, your Java objects need to conform to the JavaBean specification. This means they need methods .getXXX() to read object properties (at least), and also .setXXX() to construct a new object. Example:
Class Inner:
package demo;
public class Inner {
public String secret;
public String getSecret() {
return secret;
}
public Inner(String arg) {
this.secret = arg;
}
}
Class Outer:
package demo;
import java.util.HashMap;
import demo.Inner;
public class Outer {
public HashMap<String, Inner> someMap;
public Outer() {
HashMap<String,Inner> hm = new HashMap<String, Inner>();
hm.put("stuff", new Inner( "happens"));
hm.put("another", new Inner( "thing"));
this.someMap = hm;
}
public HashMap getSomeMap() { return someMap; }
}
and Clojure code to decode the nested JavaBean objects:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:require
[clojure.java.data :as jd])
(:import [demo Calc]))
(dotest
(let [java-obj (Outer.)
obj-shallow (jd/from-java java-obj)
obj-deep (jd/from-java-deep java-obj {})]
(spyx java-obj)
(spyx obj-shallow)
(spyx-pretty obj-deep)
))
The results show what happens:
--------------------------------------
Clojure 1.10.2-alpha1 Java 14
--------------------------------------
lein test tst.demo.core
java-obj => #object[demo.Outer 0x138d8219 "demo.Outer#138d8219"]
obj-shallow => {:someMap {"another" #object[demo.Inner 0x8d86c4d "demo.Inner#8d86c4d"], "stuff" #object[demo.Inner 0x28c92c51 "demo.Inner#28c92c51"]}}
obj-deep => {:someMap {"another" {:secret "thing"},
"stuff" {:secret "happens"}}}
The raw java-obj is opaque to Clojure. Using jd/from-java only unpacks the outer layer using the JavaBean getters. Using jd/from-java-deep (notice the required options map, left empty here) will recursively unpack the JavaBean using the appropriate getters on each object based on its java class.
All of the above code is based on this template project. Enjoy!
Clojure's built-in bean function only does a shallow conversion -- it doesn't recursively convert any nested information. Check out https://github.com/clojure/java.data for a recursive conversion from Java objects to Clojure data structures (and back).
java.data also support "builder"-style Java APIs so you can build Java objects more easily from Clojure.
Provided that abs and avg are defined:
(defn sqrt [x]
(letfn [(s [guess]
(if (good-enough? guess)
guess
(s (improve guess))))
(good-enough? [guess]
(< (abs (- (square guess) x)) 0.0001))
(improve [guess]
(avg (/ x guess) guess))]
(s 1.0)))
Please ignore for a sec that I'm reinventing the wheel here. :) This only serves as an example.
If so, is there a way to get around this so the names won't be bound again and again every time the function is called, and without introducing more names outside the function?
Will the functions defined in letfn be redefined every time sqrt is called?
Yes.
The bindings of s and good-enough will be remade every time the sqrt function is entered. The things they are bound to are constructed afresh.
The s and good-enough functions (effectively fn special forms)
are compiled once, when the (defn sqrt ... ) is
performed.
They are closed over x for every call of sqrt.
The closures might be implemented on the JVM as inner classes
complying with the IFn interface.
The closures/function-objects are constructed every time sqrt is
entered, though the classes that they exemplify have been long compiled.
It depends what you mean by redefined. I thought not, but the elements on both sides of the bindings are renewed. So now I think so.
is there a more idiomatic way to write the square root function?
Yes.
On the JVM ...
(defn sqrt [x] (Math/sqrt x))
(sqrt 2);1.4142135623730951
The short answer is "yes", the bindings will be renewed. However, this is as cheap as instantiating a very simple class. You can see below the decompiled java classes how the clojure is implemented with a simple parameter and how nested functions will result in just some more classes. So this is still very cheap.
public final class user$sqrt extends AFunction {
public static final Object const__0 = Double.valueOf(1.0D);
public static Object invokeStatic(Object x) {
user$sqrt$s__44945 s = null;
user$sqrt$good_enough_QMARK___44947 good_enough_QMARK_ = null;
user$sqrt$improve__44949 improve = null;
s = new user$sqrt$s__44945(good_enough_QMARK_, improve);
good_enough_QMARK_ = new user$sqrt$good_enough_QMARK___44947(x);
Object var10002 = x;
x = null;
improve = new user$sqrt$improve__44949(var10002);
user$sqrt$s__44945 var10000 = (user$sqrt$s__44945)s;
((user$sqrt$s__44945)s).good_enough_QMARK_ = good_enough_QMARK_;
var10000.improve = improve;
user$sqrt$good_enough_QMARK___44947 var4 = (user$sqrt$good_enough_QMARK___44947)good_enough_QMARK_;
user$sqrt$improve__44949 var5 = (user$sqrt$improve__44949)improve;
return ((IFn)s).invoke(const__0);
}
}
public final class user$sqrt$good_enough_QMARK___44947 extends AFunction {
Object x;
public static final Var const__1 = (Var)RT.var("user", "abs");
public static final Var const__3 = (Var)RT.var("user", "square");
public user$sqrt$good_enough_QMARK___44947(Object var1) {
this.x = var1;
}
public Object invoke(Object guess) {
DO var10000 = (DO)const__1.getRawRoot();
DO var10001 = (DO)const__3.getRawRoot();
Object var10002 = guess;
guess = null;
return Numbers.lt(var10000.invokePrim(RT.doubleCast((Number)Numbers.minus(var10001.invokePrim(RT.doubleCast((Number)var10002)), this.x))), 1.0E-4D)?Boolean.TRUE:Boolean.FALSE;
}
}
public final class user$sqrt$improve__44949 extends AFunction {
Object x;
public static final Var const__0 = (Var)RT.var("user", "avg");
public user$sqrt$improve__44949(Object var1) {
this.x = var1;
}
public Object invoke(Object guess) {
DDO var10000 = (DDO)const__0.getRawRoot();
double var10001 = RT.doubleCast((Number)Numbers.divide(this.x, guess));
Object var10002 = guess;
guess = null;
return var10000.invokePrim(var10001, RT.doubleCast((Number)var10002));
}
}
Well the wiseguy answer is that it would be most idiomatic not to define your own square root operation. (Math/sqrt x) which is an interop call against java.util.Math.sqrt() would be preferred. It's fairly common to see (defn sqrt [x] (Math/sqrt x)) floating around, or at least that's something I've perpetrated for several projects.
An even better answer would be to use clojure.algo.generic which already defines sqrt among other operations in an extensible and idiomatic fashion.
This particular implementation of Newton's Method is fine, and in a very traditional scheme style, but because it's using boxed arithmetic through multiple fns it will be vastly outperformed by Math/sqrt and it provides none of the numeric tower flexibility of algo.generic, or an equivalent implementation atop algo.generic.
As to will the functions in the letfn be redefined every time, the traditional Scheme implementation of letfn is something like:
Create a binding to nil for every fn name
setq each binding to the fn body now that there is a binding for every name
Evaluate the body form(s)
Clojure does the same thing under the hood. Each fn in the letfn is compiled to an AFn instance class, which accepts as instance arguments references to the closed over fns. The emitted bytecode is logically the same format as the Scheme implementation:
Bind the named local for each fn to a Var
Initialize each AFn instance with the Vars corresponding to the other letfn bodies that it closes over
Bind each instantiated AFn to the appropriate Var
Evaluate the body form(s)
So technically yes, each binding in the letfn needs to be re-established each time the body is executed, and the new binding is of a new (anonymous) Var to a new AFn instance of the compiled classes. No lambda lifting or any other transformation occurs to prevent this, however the overhead from doing so is negligible.
The following code shows the difference. Note that a plain let is all you need to define local functions:
(defn my-inc [x] (+ 1 x))
(defn my-square [x] (* x x))
(println :1 (my-square (my-inc 2)))
(let [my-inc-2 (fn [x] (+ 1 x))
my-square-2 (fn [x] (* x x)) ]
(println :2 (my-square-2 (my-inc-2 2))))
(println :sqrt-9 (Math/sqrt 9))
;=> :1 9
;=> :2 9
;=> :sqrt-9 3.0
The only difference between the 2 cases is that visibility of my-inc-2 and my-square-2 is restricted to the let block. I like this way better than using letfn, as I think the regular (fn ...) syntax is clearer.
With regards to sqrt, using the Java built-in function is much better than writing your own.
For numerical techniques in general, one effective technique is to use a polynomial first approximation, followed up by a few iterations of Newton's method. This is how Matlab computes the normal distribution function N(0,1), for example.
I am doing a library in ClojureScript that will expose a public JavaScript API. Since it has to mimic the API of an existing JavaScript library, I would like to present the same kind of fluent API :
myLib.prepareToDo()
.something()
.and('also')
.somethingElse()
.run(function(err, result) {
console.log("yay!");
});
In Javascript, one could create a fluent API like this site point):
var MyClass = function(a) {
this.a = a;
}
MyClass.prototype.foo = function(b) {
// Do some complex work
this.a += Math.cos(b);
return this;
}
I can then call it like :
var obj = new MyClass(5);
obj.foo(1).foo(2).foo(3);
Now, as far as I know, there is no notion of this in ClojureScript, although apparently it is possible to access it this-as.
I don't get how to use it though, hence my question.
How can I create a fluent interface in ClojureScript ?
(defrecord) and this answer to the rescue. Extending the "magic" protocol Object to our record or type causes the defined methods to appear as member functions in the JavaScript object. To enable the "fluent interface", some methods return an instance of MyClass.
(defrecord MyClass [a b]
Object
(something [this] this)
(and-then [this s] (assoc this :a s))
(something-else [this] (assoc this :b (str a "-" a)))
(run [this f] (f a b)))
Then we can have a JavaScript client like so:
var myClass = new my_namespace.core.MyClass();
myClass.something()
.and_then("bar")
.something_else()
.run(function(a, b) {
console.log(a + " - " + b) });
am new at clojure and would like to interact with java objects using clojure. If I have well understood,
one can reach this interaction using defprotocol.
What I concretely try to do is the following:
1- I have following java class
package mytestspackage;
public class TestObject {
private String lastName;
private String firstName;
private String age;
public TestObject(String lastName, String firstname, String age) {
super();
this.lastName = lastName;
this.firstName = firstname;
this.age = age;
}
public String getName() {
return this.lastName;
}
public void setName(String name) {
this.lastName = name;
}
public String getFirstname() {
return this.firstName;
}
public void setFirstname(String vorname) {
this.firstName = vorname;
}
public String getAge() {
return this.age;
}
public void setAge(String age) {
this.age = age;
}
}
2- I create a clojure protocol that should allow me to access to instances of the above java class TestObject
(ns mytestspackage)
(defprotocol Test
(first-name [t])
(last-name [t])
(age [t]))
Now my question is: where do I concretly implement the methods defined in the protocol and how do I use this implementation to pass TestObject instances to the clojure side and access to values like first name, last name etc...
Any help would be appreciated.
Thanks in advance.
Regards, Horace
If I have well understood, one can reach this interaction using
defprotocol.
No, you've got it wrong. Protocols are intended to allow things similar to what interfaces allow in plain java (though more powerful). You can access your Java class without any protocols. Official clojure documentation on this topic: http://clojure.org/java_interop
Example:
(ns example
(:import mytestpackage.TestObject))
;; This is how we call methods on java objects
(defn first-name [obj]
(.getFirstname obj))
(defn last-name [obj]
(.getName obj))
(defn age [obj]
(.getAge obj))
(defn set-first-name [obj name]
(.setFirstname obj name))
(defn set-last-name [obj name]
(.setName obj name))
(defn set-age [obj age]
(.setAge obj age))
;; In REPL
example => (let [x (TestObject. nil nil nil) ;; This is how we create Java objects
x (new TestObject nil nil nil)] ;; These expressions are equivalent
(println (first-name x))
(set-first-name x "Name")
(println (first-name x))
(set-last-name x "Last name")
(set-age x "23")
(println (last-name x))
(println (age x)))
;; Outputs
nil
Name
Last name
23
Please note that this code is nothing more than example intended to introduce java interop. By no means you should write real programs like that, especially if they are mostly in Clojure.
If you just want to interact with java objects using Clojure and not implement new functionality on them you don't need to worry about protocols. Clojure provides direct access and syntax for java method calls.
For example strings in Clojure are java.lang.String objects:
user=> (type "Really a Java String")
;; java.lang.String
user=> (.toUpperCase "Really a java string")
;;=> "REALLY A JAVA STRING"
Provided your test object class is on the classpath you can create instances like so:
user=> (def a-test-object (mytestpackage/TestObject. "lastName" "firstName" 42))
And call methods like:
user=> (.getAge a-test-object)
See http://clojure.org/java_interop for more info.
I am trying to get javafx2 working with Clojure - In implementing an abstract class such as DoubleBinding, I am unsure what the equivalent of super.bind(moo) is in Clojure. The class I am implementing can be found here: http://docs.oracle.com/javafx/2/api/index.html.
(def moo (ObservableDoubleValue. ...))
(def foo (proxy [DoubleBinding] []
(computeValue []
(Math/sqrt (.getValue moo)))))
final ObservableDoubleValue moo = ...;
DoubleBinding foo = new DoubleBinding() {
{
super.bind(moo);
}
#Override
protected double computeValue() {
return Math.sqrt(moo.getValue());
}
};
According to proxy documentation, methods in proxy has no access to super... I would recommend you to generate class using gen-class and use it. You can access to super's methods if you'll expose them with :exposes-methods directive. Something, like:
(gen-class :name MyDoubleBinding
:extends DoubleBinding
:exposes-methods {bind my-bind}
....
)
and then call -my-bind from your constructor...
Please, check documentation about class generation on Clojure's site for more details on gen-class