On May 26, 3:54 pm, Stuart Sierra <
the.stuart.sie...@gmail.com> wrote:
> Is it possible to define Java enum types directly in Clojure or with
> proxies/reflection?
On May 28, 7:35 am, Rich Hickey <
richhic...@gmail.com> wrote:
> One thing to note is that all (proxy [Enum]...) will have the same
> class.
<snip>
> So, you have 3 options before going to Java:
>
> (proxy [Enum] ...) - subject to the all-the-same-class caveat above
>
> (gen-and-load-class
your.class.Name :extends Enum ...) - to get unique
> names, which will be available for use in Clojure code
<snip>
Thanks, Rich. Both of these work:
(def counter1 (proxy [Enum] ["Counter1" 1]))
(def counter2 (proxy [Enum] ["Counter2" 2])) ; funny class name
;; OR
(gen-and-load-class "my.package.Counters" :extends Enum)
(def counter1 (new my.package.Counters "Counter1" 1))
(def counter2 (new my.package.Counters "Counter2" 2))
I noticed the genclass stuff in SVN a while ago -- was wondering when
you would bring it up on the list!
For fun, I even made a macro:
(defmacro defenum [class & symbols]
(try (. Class (forName (str class)))
(catch java.lang.ClassNotFoundException e
(gen-and-load-class (str class) :extends java.lang.Enum)))
(cons 'do
(map (fn [sym val]
`(def ~symbol (new ~class ~(str sym) ~val)))
symbols (iterate inc 1))))
The try/forName bit is to prevent the class from being loaded more
than once. Now I can do:
(defenum my.package.Counters Counter1 Counter2)
This does, of course, break every type safety constraint on Java's
enums. Long live dynamic typing!
(.isEnum (class Counter1)) returns false, but otherwise it's a real
Java Enum.