Frage

Sagen Sie, ich habe einen Java Enum. Zum Beispiel:

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

Normalerweise kann ich etwas in Clojure mit diesem Enum so tun:

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

Ich möchte jedoch eine Clojure -Funktion schreiben, mit der der Anrufer angeben kann, welche Enum -Instanz verwendet werden soll:

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

Die Idee ist, einen Anrufer einzugeben "DIAMONDS" und haben die DIAMONDS Enum -Instanz werden an gebunden an gebunden s in dem let.

Ich könnte eine haben cond Übereinstimmung gegen den Parameter, aber das scheint klobiger als nötig. Ich nehme an, ich könnte auch ein Makro verwenden, um zu konstruieren Suits/ hinzugefügt zu suit. Ist dies der Weg, dies zu tun, oder gibt es eine nicht-makrische Art und Weise, wie ich fehlt?

War es hilfreich?

Lösung

Keine Reflexion oder Karten. Jeder Java Enum hat eine statische valueOf Methode, die einen Enumswert nach Namen abruft. So:

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

Verwendung (name) Ermöglicht entweder Zeichenfolgen oder Schlüsselwörter:

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

Andere Tipps

Ich habe vor langer Zeit eine ähnliche Frage gestellt, nicht in Bezug auf Aufzüge, sondern statische Klassenmitglieder im Allgemeinen: Wie kann ich ein statisches Klassenmitglied in Clojure dynamisch nachsehen?

Die Antwort war, Java Reflection zu verwenden:

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

Um die Leistung zu verbessern, können Sie beispielsweise eine Karte mit der Zeichenfolge erstellen, die Sie übereinstimmen möchten, zum Beispiel:

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

Dann würde es in der Funktion von etwas do the do etwas aussehen:

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

Und Sie können diese Karte während der Ladezeit mit Reflexion (statt von Hand) erstellen, aber während der Laufzeit ist es nur eine Karten -Lookup.

(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#)))
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top