No matching method with Clojure Java interop using reify - clojure

I have a misunderstanding about a certain Clojure/Java interop.
I'm using the Pi4J library and I want to get a listener on a GPIO Pin.
The usage documentation: https://pi4j.com/1.2/usage.html (under "Listen for Pin Changes") gives the following example:
public static class GpioUsageExampleListener implements GpioPinListenerDigital {
#Override
public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
// display pin state on console
System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = "
+ event.getState());
}
}
// create and register gpio pin listener
myButton.addListener(new GpioUsageExampleListener());
There is also an example application: https://pi4j.com/1.2/example/listener.html
Which has:
myButton.addListener(new GpioPinListenerDigital() {
#Override
public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
// display pin state on console
System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
}
});
So, I'm trying the following bit of Clojure code:
(import [com.pi4j.io.gpio GpioFactory GpioPinDigitalInput PinPullResistance RaspiPin]
[com.pi4j.io.gpio.event GpioPinListenerDigital])
(def gpio (GpioFactory/getInstance))
(def mybutton (.provisionDigitalInputPin gpio RaspiPin/GPIO_02 PinPullResistance/PULL_DOWN))
(def gpio-listener (reify GpioPinListenerDigital
(handleGpioPinDigitalStateChangeEvent [this event]
(println "GPIO Event Occured"))))
(.addListener mybutton gpio-listener)
But I get:
No matching method addListener found taking 1 args for class com.pi4j.io.gpio.impl.GpioPinImpl
Using reflection, I have a look at the methods available to the mybutton instance, and I can see the method is there:
(clojure.reflect/reflect mybutton)
:members
#{{
;;; Stuff trimmed
{:name addListener,
:return-type void,
:declaring-class com.pi4j.io.gpio.impl.GpioPinImpl,
:parameter-types [java.util.List],
:exception-types [],
:flags #{:public :synchronized}}
{:name addListener,
:return-type void,
:declaring-class com.pi4j.io.gpio.impl.GpioPinImpl,
:parameter-types [com.pi4j.io.gpio.event.GpioPinListener<>],
:exception-types [],
:flags #{:varargs :public :synchronized}}}}
I've checked the type of gpio-listener against GpioPinListener with success.
(cast com.pi4j.io.gpio.event.GpioPinListener gpio-listener)
#object[user$reify__7404 0x11251bd "user$reify__7404#11251bd"]
I tried type hinting the parameter to GpioPinListener, but I get the same result.
My lack of Clojure and Java knowledge is failing me here, so I'm a little lost where to look next, but I'm sure it's something really basic.

I can't test this, but if you note the docs, you'll see that addListener is actually var-arg, and dealing with var-arg methods can be confusing due to misunderstandings of how var-arg methods in Java work .
addListener is expecting an array of listeners (which is sugared away by Java var-arg syntax). Try
(.addListener mybutton
(into-array [gpio-listener]))
Or, since addListener actually has a List overload, this may work too
(.addListener myButton [gpio-listener])

Related

How to convert Java 17 record to Clojure map?

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)])))

Is it possible to define a macro: anything else to dispatch on functions?

I don't know how to really name my problem since I do not know how to even start thinking about this so I will state the problem.
Imagine I have several static methods of a Java object which use the same syntax, for instance:
https://github.com/deeplearning4j/nd4j/blob/master/nd4j-backends/nd4j-api-parent/nd4j-api/src/main/java/org/nd4j/linalg/ops/transforms/Transforms.java
/**
* Floor function
*
* #param ndArray
* #return
*/
public static INDArray floor(INDArray ndArray, boolean dup) {
return exec(dup ? new Floor(ndArray.dup()) : new Floor(ndArray));
}
/**
* Signum function of this ndarray
*
* #param toSign
* #return
*/
public static INDArray sign(INDArray toSign, boolean dup) {
return exec(dup ? new Sign(toSign, toSign.dup()) : new Sign(toSign));
}
So here is a sample dummy wrapper:
(defn floor
^INDArray
[^INDArray a ^boolean dup]
(Transforms/floor a dup))
(defn sign
^INDArray
[^INDArray a ^boolean dup]
(Transforms/sign a dup))
The problem here is that you waste time to write functions with identical templates which is OK for the first time... but imagine you want to update ALL of them in case of a change/broken code/performance tuning/whatever.
I searched the problem but found nothing about it. The ideal case would be (a macro?) like:
(defoperator floor Transforms/floor)
Or
(def floor (->operator Transforms/floor))
I don't know if it is possible to call a "generic" static method for starters even if it is a quite common use case and did not find any answer.
I suspect it is not the case since typing "Transforms/floor" in repl treats it as a static field and not method but I am not sure.
You could write a macro that expands to a function definition containing the duplicate code:
(defmacro defoperator [op]
`(defn ~op ; Create a function with "op" as the name
^INDArray
[^INDArray a#, dup#]
(. Transforms ~op a# dup#))) ; (. Transforms floor) is the same as (Transforms/floor)
Calling (defoperator floor) now emits a function definition that looks like:
(defn floor
^INDArray
[^INDArray a, dup]
(. Transforms floor a dup))
This macro assumes that the static method name is the same as the function that you want emitted. If you want them to potentially differ, you can use an alternate version:
(defmacro defoperator [fn-name static-name]
`(defn ~fn-name
^INDArray
[^INDArray a#, dup#]
(. Transforms ~static-name a# dup#)))
Note, I got rid of your ^boolean hint. You can't hint Boolean primitives. I'm not sure what version of Clojure you're using, but that doesn't work in 1.8.0.

Will the bindings defined in `letfn` be renewed every time `sqrt` is called?

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.

Protocol functions return a result faster if the constant it returns isn't cached

I'm writing an Entity Component System. Part of it is a protocol that defines how Systems are used. Part of the protocol is a function that returns the components that the system requires to function. It can be distilled down to the following:
(defprotocol System
(required-components [sys]
"Returns a map of keys and initial values of components that the System requires to operate.")
Because the value that this function returns is really a constant, I thought that caching it would probably be a good idea because it might be required +60 times a second. To tell whether or not it makes a difference though, I wrote up the following test:
(defrecord Input-System1 []
System
(required-components [sys] {:position [0 0] :angle 0}))
(def req-comps
{:position [0 0] :angle 0})
(defrecord Input-System2 []
System
(required-components [sys] req-comps))
Then in a REPL, I ran the following time tests:
(let [sys (->Input-System1)]
(time-multiple 1000000000
(required-components sys)))
(let [sys (->Input-System2)]
(time-multiple 1000000000
(required-components sys)))
(Code for time-multiple below).
The odd thing is, Input-System1 consistently finishes faster than Input-System2: 2789.973066ms vs 3800.345803ms on the last run.
I find this odd though given how, in theory, version 1 is constantly recreating the component map, while version 2 only references a pre-defined value.
I tried recreating this by cutting protocols out:
(defn test-fn1 []
req-comps)
(defn test-fn2 []
{:position [0 0] :angle 0})
(time-multiple 1000000000
(test-fn1))
(time-multiple 1000000000
(test-fn2))
But this time, the results end up being almost identical: 3789.478675ms vs 3767.577814ms.
This leads me to believe it has something to do with protocols, but I can't tell what. What's going on here? I know that given the number of tests, 1000ms is fairly insignificant, so I'm not trying to micro-optimize here. I'm just curious.
(defmacro time-pure
"Evaluates expr and returns the time it took.
Modified the native time macro to return the time taken."
[expr]
`(let [start# (current-nano-timestamp)
ret# ~expr]
(/ (double (- (current-nano-timestamp) start#)) 1000000.0)))
(defmacro time-multiple
"Times the expression multiple times, returning the total time taken, in ms"
[times expr]
`(time-pure
(dotimes [n# ~times]
~expr)))
In either case your map is a constant, created during class loading (it's statically known, so no new object creation during the method call.) On the other hand, your cached case costs you an extra indirection - accessing a var.
To demonstrate:
(def req-comps
{:position [0 0] :angle 0})
(defn asystem-1 []
{:position [0 0] :angle 0})
(defn asystem-2 []
req-comps)
(It doesn't matter whether we deal with protocols or not - the functions are compiled the same, it's just easier to find them in the compiled code this way.)
public final class core$asystem_1 extends AFunction {
public static final AFn const__4 = (AFn)RT.map(new Object[]{RT.keyword((String)null, "position"), Tuple.create(Long.valueOf(0L), Long.valueOf(0L)), RT.keyword((String)null, "angle"), Long.valueOf(0L)});
public core$asystem_1() {
}
public static Object invokeStatic() {
return const__4;
}
public Object invoke() {
return invokeStatic();
}
}
See - it just returns the precalculated constant.
public final class core$asystem_2 extends AFunction {
public static final Var const__0 = (Var)RT.var("so.core", "req-comps");
public core$asystem_2() {
}
public static Object invokeStatic() {
return const__0.getRawRoot();
}
public Object invoke() {
return invokeStatic();
}
}
An extra call to getRawRoot().

Clojure: extend Wicket panel and call to panel methods

Currently I'm trying to create sample Wicket page with Clojure (in existing wicket project). Code looks like this:
(ns a.set.of.packages.dataview.info.EmptyNodeInfo2Panel
(:import [a.set.of.packages.tree TreeModelBean]
[a.set.of.packages.dataview.supplemental GenericHeaderPanel]))
(gen-class
:name a.set.of.packages.dataview.info.EmptyNodeInfo2Panel
:extends org.apache.wicket.markup.html.panel.Panel
:state state
:init init
:constructors {[String a.set.of.packages.tree.TreeModelBean] [String]}
:post-init construct)
(defn -init [id model-bean]
[[id] nil])
(defn -construct [this id model-bean]
(.add this (GenericHeaderPanel. "header" model-bean)))
When page being created I get following runtime error:
java.lang.IllegalArgumentException: No matching method found: add for class a.set.of.packages.dataview.info.EmptyNodeInfo2Panel
i.e. I can't call to the superclass methods.
Decompiled construct method looks like this:
public Object invoke(Object this, Object id, Object model_bean)
throws Exception
{
this = null;
id = null;
model_bean = null;
return Reflector.invokeInstanceMethod(this, "add", new Object[] {
new GenericHeaderPanel((String)"header", (TreeModelBean)model_bean)
});
}
Where everything is set to null! Is this problem with constructor parameters mapping, incorrect decompilation or a bug?
I've dug in Clojure internals and found root of the problem. Marked row doesn't work.
// clojure.lang.Reflector
static public boolean paramArgTypeMatch(Class paramType, Class argType)
{
...
if(paramType == argType || paramType.isAssignableFrom(argType)) // <<<
return true;
...
Probably there is class loader problem (I create EmptyNodeInfo2Panel class dynamically with Class.forName).
Classes that was matched are:
a.set.of.packages.dataview.supplemental.GenericHeaderPanel
org.apache.wicket.Component;
Interesting thing: when I print org.apache.wicket.Component class name from servlet respnose processing thread it prints as is, but when I print it from Reflector thead (through paramType.getName()), it prints in following form: [Lorg.apache.wicket.Component.
I use Tomcat 5.5, are there any clues possible?