Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cast explicitly in clojure when interfacing with java

In trying to use weka from clojure, I'm trying to convert this howto guide from the weka wiki to clojure using the java interop features of clojure.

This has worked well so far, except in one case, where the clojure reflection mechanism can't seem to find the right method to invoke - I have:

(def c-model (doto (NaiveBayes.) (.buildClassifier is-training-set)))

Later this will be invoked by the .evaluateModel method of the Evaluation class:

(.evaluateModel e-test c-model is-testing-set)

where e-test is of type weka.classifiers.Evaluation and, according to their api documentation the method takes two parameters of types Classifier and Instances

What I get from clojure though is IllegalArgumentException No matching method found: evaluateModel for class weka.classifiers.Evaluation clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:53) - I guess that this is because c-model is actually of type NaiveBayes, although it should also be a Classifier - which it is, according to instance?.

I tried casting with cast to no avail, and from what I understand this is more of a type assertion (and passes without problems, of course) than a real cast in clojure. Is there another way of explicitly telling clojure which types to cast to in java interop method calls? (Note that the original guide I linked above also uses an explicit cast from NaiveBayes to Classifier)

Full code here: /http://paste.lisp.org/display/129250

like image 359
Yefim Dinitz Avatar asked May 01 '12 18:05

Yefim Dinitz


2 Answers

The linked javadoc contradicts your claim that there is a method taking a Classifier and an Instances - what there is, is a method taking a Classifier, an Instances, and a variable number of Objects. As discussed in a number of SO questions (the only one of which I can find at the moment is Why Is String Formatting Causing a Casting Exception?), Clojure does not provide implicit support for varargs, which are basically fictions created by the javac compiler. At the JVM level, it is simply an additional required parameter of type Object[]. If you pass a third parameter, an empty object-array, into your method, it will work fine.

like image 116
amalloy Avatar answered Oct 22 '22 02:10

amalloy


IllegalArgumentException No matching method found happens anytime the arguments don't match the class. They can fail to match because no method exists with that name and number of arguments or because no method exists with that name in the called class. so also check the number and type of the arguments.

I basically always resort to repl-utils/show in these cases

like image 41
Arthur Ulfeldt Avatar answered Oct 22 '22 01:10

Arthur Ulfeldt