In Clojure, how to use a java Class that is stored in a variable?
How should I fix the following code?
(def a java.lang.String)
(new a "1"); CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: a
And why this one works fine?
(def a str)
(a "1")
The most elegant solution is to write construct that does the same as new but is able to receive a class dynamically:
(defn construct [klass & args]
(clojure.lang.Reflector/invokeConstructor klass (into-array Object args)))
(def a HashSet)
(construct a '(1 2 3)); It works!!!
This solution overcomes the limitation of #mikera's answer (see comments).
Special Thanks to #MichaĆ Marczyk that made me aware of invokeConstructor answering another question of mine: Clojure: how to create a record inside a function?.
Another option is to store the call to the constructor as an anonymous function. In our case:
(def a #(String. %1))
(a "111"); "111"
When you define a in this way, you get a var containing a java.lang.Class
(def a java.lang.String)
(type a)
=> java.lang.Class
You then have 2 options:
A: Construct the new instance dynamically by finding the Java constructor using the reflection API. Note that as Yehonathan points out you need to use the exact class defined in the constructor signature (a subclass won't work as it won't find the correct signature):
(defn construct [klass & args]
(.newInstance
(.getConstructor klass (into-array java.lang.Class (map type args)))
(object-array args)))
(construct a "Foobar!")
=> "Foobar!"
B: Construct using Clojure's Java interop, which will require an eval:
(defn new-class [klass & args]
(eval `(new ~klass ~#args)))
(new-class a "Hello!")
=> "Hello!"
Note that method A is considerably faster (about 60x faster on my machine), I think mainly because it avoids the overhead of invoking the Clojure compiler for each eval statement.
The problem is that Clojure implements Java interop using a number of special forms:
user=> (doc new)
-------------------------
new
Special Form
Please see http://clojure.org/special_forms#new
nil
this basically means the "normal" Clojure syntax is altered to allow for handier constructs when calling Java. As a naive reflection solution to your dynamic Java needs, you can leverage eval:
user=> (def a String) ; java.lang package is implicitly imported
#'user/a
user=> `(new ~a "test") ; syntax quote to create the correct form
(new java.lang.String "test")
user=> (eval `(new ~a "test")) ; eval to execute
"test"
The same strategy works with all the other interop special forms, like method invocation.
EDIT: look also at the answer from #mikera for a more performing alternative via the Java reflection API.
Related
Are functions dispatched by defmulti executing in the context/scope of the dispatcher?
I want to set a dynamic var *foo* for dispatched defmethod call.
I have a feeling that I will need to wrap the call to the dispatcher but wanted to confirm with the Clojure magicians.
RESOLVED
As per underlying suspicions confirmed by #schaueho, the following does what I need
;; Multimethod dispatch
(defmulti consume :type)
;; wrapper for dispatch
(defn consume-it [{:keys [token-fn]:as expression}]
"Wraps consume to imbue term name resolutions"
(if token-fn
(binding [*lookup-fn* token-fn]
(consume expression))
(consume expression)))
If I understand you correctly, you would like to use binding within the dispatch function. The purpose of the dispatch function is to return a value that will be used to identify the method to invoke, not to actually call the identified method.
(def ^:dynamic *dynvar* nil)
(defmulti mymulti
(fn [two args]
(binding [*dynvar* (new-value two args)]
(compute-dispatch-value two args)))
In this example, compute-dispatch-value would be see the new binding of *dynvar*, but any invoked method afterwards wouldn't.
I am not able to find any documentation (or blogs) regarding this. Is it possible to call package protected methods from clojure? We have a huge java code base and I was thinking if its possible to start developing some clojure libraries around them.
I tried making the namespace same as that of the package in java but the method (static) was not found.
Here's a quick code example:
(def a (ref 0))
(def klass (class a))
(def m (.getDeclaredMethod klass "currentVal" (into-array Class [])))
(.setAccessible m true)
(.invoke m a (into-array []))
You should probably have a look at the reflect API
Although, I would recommend only using the publicly declared fields and methods from your old java code base.
I have a method on an object.
myObject.myMethod(1)
I can invoke this in Clojure
(.myMethod myObject 1)
I can also invoke it using information from the lexical environment
(let [x 1] (.myMethod myObject x))
Can I do this with a partial? E.g.
(let [myPartial (partial .myMethod myObject)]
(myPartial 1))
This gives me a
java.lang.RuntimeException: Unable to resolve symbol: .myMethod in this context
I'm currently making this work with an anonymous function
(let [myThing #(.myMethod myObject %)]
(myThing 1))
But if it would be nice to use a partial in this case. Is it possible?
I'm sure the answer will be to do with binding and dispatch but I don't yet have a feeling for where during the compiling and execution the dispatch happens.
You can have partial in your case, use (memfn).
(memfn myMethod args)
In the REPL:
user=> (doc memfn)
-------------------------
clojure.core/memfn
([name & args])
Macro
Expands into code that creates a fn that expects to be passed an
object and any args and calls the named instance method on the
object passing the args. Use when you want to treat a Java method as
a first-class fn. name may be type-hinted with the method receiver's
type in order to avoid reflective calls.
For the sake of example, suppose I've wrapped a StringBuilder in a function so I can use it more easily in Clojure. I can easily make the no-arg version of the function call toString on the buffer e.g.
(defn builder
([^StringBuilder sb]
(fn
([] (.toString sb))
([& args]
(doseq [arg args]
(.append sb arg)))))
([] (builder (StringBuilder.))))
This is perfectly workable, however, I wonder how I could just override .toString() on the function itself so I could return the state of the StringBuilder or any other object that I have closed over.
You could try using https://github.com/technomancy/serializable-fn, which makes functions include their closed-over scope when they print. It will print the pr-str of the stringbuilder, though, which may or may not be exactly what you want.
defn = public
defn- = private
Perhaps I have bad Clojure coding style -- but I find that most functions I write in Clojure are small helper functions that I do not want to expose.
Is there some configuration option, where:
defn = private by default,
and to make something public, I have to do defn+?
Thanks!
No. There is not.
An alternative approach which might or might not work for you is to declare a foo.bar.internal namespace containing all the private helpers which is used by your foo.bar namespace. This has advantages over private function declarations when you want to use private functions in macro expansions.
If the "helper functions" are very likely to be used once, you could choose to make them locals of your bigger functions, or write them as anonymous functions. See letfn: http://clojuredocs.org/clojure_core/clojure.core/letfn and http://clojuredocs.org/clojure_core/clojure.core/fn.
I hardly ever use letfn myself.
The beauty of Clojure being a Lisp, is that you can build and adapt the language to suit your needs. I highly recommend you read On Lisp, by Paul Graham. He now gives his book away for free.
Regarding your suggestion of defn+ vs defn vs defn-. This sound to me like a good case for writing your own Macro. defn is a function and defn- is a macro. You can simply redefine them as you wish, or wrap them in your own.
Here follows a suggestion to implementation, based mainly on Clojure's own implementation - including a simple utility, and a test.
(defmacro defn+
"same as Clojure's defn, yielding public def"
[name & decls]
(list* `defn (with-meta name (assoc (meta name) :public true)) decls))
(defmacro defn
"same as Clojure's defn-, yielding non-public def"
[name & decls]
(list* `defn (with-meta name (assoc (meta name) :private true)) decls))
(defn mac1
"same as `macroexpand-1`"
[form]
(. clojure.lang.Compiler (macroexpand1 form)))
(let [ ex1 (mac1 '(defn f1 [] (println "Hello me.")))
ex2 (mac1 '(defn+ f2 [] (println "Hello World!"))) ]
(defn f1 [] (println "Hello me."))
(defn+ f2 [] (println "Hello World!"))
(prn ex1) (prn (meta #'f1)) (f1)
(prn ex2) (prn (meta #'f2)) (f2) )
As stated by #kotarak, there is no way (as far as I know) to do that, nor is it desirable.
Here is why I dislike defn- :
I found out that when using various Clojure libraries I sometimes need to slightly modify one function to better suit my particular needs.
It is often something quite small, and that makes sense only in my particular case. Often this is just a char or two.
But when this function reuses internal private functions, it makes it harder to modify. I have to copy-paste all those private functions.
I understand that this is a way for the programmer to say that "this might change without notice".
Regardless, I would like the opposite convention :
always use defn, which makes everything public
use defn+ (that doesn't exist yet) to specify to the programmer which functions are part of the public API that he is supposed to use. defn+ should be no different from defnotherwise.
Also please note that it is possible to access private functions anyway :
;; in namespace user
user> (defn- secret []
"TOP SECRET")
;; from another namespace
(#'user/secret) ;;=> "TOP SECRET"