Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attaching metadata to a Clojure gen-class

Is it possible to attach metadata to a Clojure gen-class?

I am trying to implement a server that uses a library that requires Java annotations added to classes.

From Chas Emerick's, et al., forthcoming book "Programming Clojure" (section 9.7.3), adding annotations to gen-class methods is easy, but there is no mention of adding class-level annotations.

like image 388
Ralph Avatar asked Oct 09 '11 12:10

Ralph


People also ask

What does Gen class do in Clojure?

An optional :gen-class directive can be used in the ns declaration to generate a named class corresponding to a namespace. (:gen-class … ​), when supplied, defaults to :name corresponding to the ns name, :main true, :impl-ns same as ns, and :init-impl-ns true.

What is gen class?

Basically, General Education (or Gen Ed for short) is required curriculum that makes up the foundation of an undergraduate degree. This set of standard classes goes by many other names, including Core Curriculum and Shared Experience.

How do you create a class in Clojure?

In Clojure we can do that using the special form new or using a dot ( . ) notation. The new special form has the class name of the Java class we want to create an instance of as argument followed by arguments for the Java class constructor. With the dot notation we place a .


3 Answers

Yes it is, I found a great example here:

https://github.com/clojure/clojure/blob/master/test/clojure/test_clojure/genclass/examples.clj

Here's some code inlined so it doesn't disappear in the future:

(gen-class :name ^{Deprecated {}
                   SuppressWarnings ["Warning1"] ; discarded
                   java.lang.annotation.Target []}
                 clojure.test_clojure.genclass.examples.ExampleAnnotationClass
           :prefix "annot-"
           :methods [[^{Deprecated {}
                        Override {}} ;discarded
                      foo [^{java.lang.annotation.Retention java.lang.annotation.RetentionPolicy/SOURCE
                             java.lang.annotation.Target    [java.lang.annotation.ElementType/TYPE
                                                             java.lang.annotation.ElementType/PARAMETER]}
                           String] void]])
like image 139
Daniel Kaplan Avatar answered Oct 20 '22 14:10

Daniel Kaplan


I don't think it is possible at this point.

Rich Hickey mentions adding annotations support in this thread https://groups.google.com/group/clojure/browse_thread/thread/d2128e1505c0c117 but as far as I can see this is only for deftype / defrecord. I could be wrong of course.

Both of these

(ns genclass.example
  (:gen-class ^{:doc "example class"}))

and

(ns genclass.example)

(with-meta
  (gen-class
   :name genclass.example.ClassA
   :methods [[hello [] void]])
  {:doc "Example class"})      

fail to compile for me. From the exception

Exception in thread "main" java.lang.IllegalArgumentException: Metadata can only be applied to IMetas (example.clj:4)`

It sounds like this is not possible.

like image 21
Paul Avatar answered Oct 20 '22 14:10

Paul


To add additional information to this because I can't find it documented anywhere else it's possible to add annotations to constructors as well.

You can add annotations to constructors by adding meta data to the first array of the constructor pair. Like this:

(gen-class
  :name "FooClass"
  :init "init"
  :constructors {^{Inject {}} [Configuration] []}
  :state "state"
  :implements [FooInterface]
  :prefix "ref-")
like image 28
zachncst Avatar answered Oct 20 '22 15:10

zachncst