Reputation: 424
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
Upvotes: 6
Views: 1124
Reputation: 91887
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.
Upvotes: 7
Reputation: 91554
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
Upvotes: 2