13

Say I have a Java enum. For example:

public enum Suits {CLUBS, DIAMONDS, HEARTS, SPADES};

Normally, I can do something in clojure with that enum like so:

(defn do-something []
   (let [s Suits/DIAMONDS] (...)))

But, I want to write a clojure function that allows the caller to specify which enum instance to use:

(defn do-something-parameterized [suit]
   (let [s  Suits/suit] (...)))

The idea is to let a caller pass in "DIAMONDS" and have the DIAMONDS enum instance get bound to s in the let.

I could have a cond match against the parameter but that seems clunkier than necessary. I suppose I could also use a macro to construct Suits/ added to suit. Is this the way to do it or is there a non-macro way that I'm missing?

4 Answers 4

14

No need for reflection or maps. Every Java enum has a static valueOf method that retrieves an enum value by name. So:

(defn do-something-parameterized [suit]
  (let [s (Suit/valueOf (name suit))] ...))

Using (name) allows either strings or keywords to be used:

(do-something-parameterized "HEARTS")
(do-something-parameterized :HEARTS)
Sign up to request clarification or add additional context in comments.

1 Comment

So obvious, Dave. I'm embarrassed I forgot about this.
1

I asked a similar question a long while ago, not regarding enums but static class members in general: How can I dynamically look up a static class member in Clojure?

The answer was to use Java reflection:

(defn do-something-parameterized [suit]
  (let [s (.get (.getField Suits suit) nil)] (...)))

Comments

0

To improve performance, you could create a map with the string that you want to match, to the enum type, for example:

 (def my-enum-map {"DIAMONDS" Suits/DIAMONDS, "SPADES" Suits/SPADES...})

Then in the do something function it would look like:

 (defn do-something-parameterized [suit]
    (let [s (my-enum-map suit)] ...))

And you can build this map during load time using reflection (instead of by hand), but during runtime, its just a map lookup.

Comments

0
(defmacro def-enum-alias
  "Make name reference enum.

   (def-enum-alias enum-name MyClass$MyEnum)

   (enum-name Foo)

   second desugars to MyClass$MyEnum/Foo"
  [name enum]
  `(defmacro ~name
     ~(str "automatically generated alias for enum "
           enum)
     [member#]
     (symbol-munge (quote ~enum) "/" member#)))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.