Как я могу параметризовать доступ к перечислению Java в clojure?

Скажем, у меня есть перечисление Java. Например:

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

Обычно я могу сделать что-то в clojure с таким перечислением, как это:

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

Но я хочу написать функцию clojure, которая позволяет вызывающему указать, какой экземпляр перечисления использовать:

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

Идея состоит в том, чтобы позволить вызывающему абоненту проходить в "DIAMONDS" и иметь экземпляр enum DIAMONDS, связанный с s в let.

Я мог бы сопоставить cond с параметром, но это кажется неуклюжим, чем необходимо. Я полагаю, что я мог бы также использовать макрос для построения Suits/, добавленного в suit. Это способ сделать это или есть не-макропоток, который мне не хватает?

Ответ 1

Не нужно отражать или отображать карты. Каждое перечисление Java имеет статический метод valueOf, который извлекает значение перечисления по имени. Итак:

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

Использование (name) позволяет использовать либо строки, либо ключевые слова:

(do-something-parameterized "HEARTS")
(do-something-parameterized :HEARTS)

Ответ 3

Чтобы повысить производительность, вы можете создать карту со строкой, которую вы хотите сопоставить, с типом перечисления, например:

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

Затем в функции do что-то будет выглядеть:

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

И вы можете построить эту карту во время загрузки с использованием отражения (а не вручную), но во время выполнения это просто просмотр карты.

Ответ 4

(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#)))