13

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"DIAMONDS列挙型インスタンスが にバインドされるようsにすることletです。

パラメータと一致する可能性がありcondますが、必要以上に扱いにくいようです。マクロを使用して、Suits/追加を構築することもできると思いますsuit。これはそれを行う方法ですか、それとも私が見逃しているマクロ以外の方法はありますか?

4

4 に答える 4

14

リフレクションやマップは必要ありません。valueOfすべての Java 列挙には、列挙値を名前で取得する静的メソッドがあります。そう:

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

(name)を使用すると、文字列またはキーワードを使用できます。

(do-something-parameterized "HEARTS")
(do-something-parameterized :HEARTS)
于 2011-09-06T00:48:21.340 に答える
1

ずっと前に、列挙型ではなく静的クラス メンバー全般に関する同様の質問をしました。Clojure で静的クラス メンバーを動的に検索するにはどうすればよいですか?

答えは、Java リフレクションを使用することでした。

(defn do-something-parameterized [suit]
  (let [s (.get (.getField Suits suit) nil)] (...)))
于 2011-09-05T22:48:41.197 に答える
0

パフォーマンスを向上させるために、一致させたい文字列を含むマップを列挙型に作成できます。次に例を示します。

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

次に、do something 関数では次のようになります。

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

また、ロード時にリフレクションを使用して (手作業ではなく) このマップを作成できますが、実行時はマップ ルックアップにすぎません。

于 2011-09-05T22:59:59.203 に答える
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#)))
于 2013-07-21T20:43:59.103 に答える