【问题标题】:How can I parameterize access to a Java enum in clojure?如何在 clojure 中参数化对 Java 枚举的访问?
【发布时间】:2011-11-10 21:35:58
【问题描述】:

假设我有一个 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 枚举实例绑定到let 中的s

我可以对参数进行cond 匹配,但这似乎比必要的要笨重。我想我也可以使用宏来构造Suits/ 添加到suit。这是这样做的方式还是我缺少一种非宏观方式?

【问题讨论】:

    标签: clojure clojure-java-interop


    【解决方案1】:
    (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#)))
    

    【讨论】:

      【解决方案2】:

      不需要反射或映射。每个 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 something 函数中它看起来像:

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

      您可以在加载时使用反射(而不是手动)构建此地图,但在运行时,它只是一个地图查找。

      【讨论】:

        【解决方案4】:

        很久以前我问过一个类似的问题,不是关于枚举,而是关于一般的静态类成员:How can I dynamically look up a static class member in Clojure?

        答案是使用 Java 反射:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-03-12
          • 2012-02-06
          • 1970-01-01
          • 2011-07-09
          • 2011-11-06
          • 1970-01-01
          • 1970-01-01
          • 2011-10-05
          相关资源
          最近更新 更多