Enums and Clojure
在Java / C世界中,人们经常使用枚举。 如果使用的Java库使用枚举,则可以在它们和关键字之间进行转换,例如,使用(. java.lang.Enum valueOf e..., (aget ^"[Ljava.lang.Enum;" (. e (getEnumConstants)) i)和一些反射。 但是在Clojure世界中,人们是否需要像枚举(命名为整数)之类的东西? 如果不是,他们的代码结构如何使其不需要它们? 如果是,等价的是多少? 我觉得我真的在问索引(用于循环),在函数编程中很少使用索引(到目前为止,我仅使用map-indexed一次)。
正如Arthur所指出的那样,在Clojure中通常使用关键字代替枚举。
您不会看到编号索引使用过多-在Clojure(或大多数其他函数式编程语言)中它们并不是特别惯用的
其他一些值得注意的选择:
-
直接使用Java枚举-例如java.util.concurrent.TimeUnit/SECONDS
-
如果需要数值,请使用vars定义自己的常量-例如(def ^:const PURPLE 1)
-
如果您想要使用简单语法的更高级枚举功能,甚至可以实现宏defenum。
-
枚举系统的潜在好处之一是可以确保在运行时不允许使用非成员值。 克洛瑞尔(Clojure)满足这种需求的最佳方式是什么?
-
在我看来,clojure方法更多地是关于使用诸如此类的验证工具/测试。 签出例如 Prismatics模式库-github.com/prismatic/schema
-
谢谢,我会检查出来的。 clj-schema似乎也是另一种选择。
-
感谢您提供用于引用Java枚举成员@mikera的Clojure语法。
-
在Clojure验证工具中,您现在可以枚举(眨眼!)Clojure Spec
-
@luskwater如何使用Spec确定一个枚举?
-
@ petrus-theron如果您使用关键字,则(sdef :dogbreed #{:labrador :huskador :husky})是检查"它必须是这些值之一"的常规方法。 集合中可以包含任何其他值,无论是Java枚举,整数还是字符串。
我见过的几乎所有Clojure代码都倾向于使用关键字而不是Enums,它们使用名称分隔,并具有关键字的所有其他有用属性,同时更容易编写。它们不是确切的替代者,因为它们比Java枚举更具动态性(例如在动态类型中)
至于索引和循环,我发现映射一系列关键字更为习惯:
1
| (map do-stuff [:a :b :c :d] (range)) |
而不是遍历枚举中的值,尽管很有可能存在示例,但我还没有找到Clojure代码中的示例;
是的,在Java程序员使用枚举的大多数地方都使用关键字。在极少数情况下,您每个人都需要一个数字的情况,您只需定义一个转换映射:{:dog 0, :rabbit 1, ...}。
另一方面,我编写的第一个Clojure库就是这样的:一个defenum宏,它为符号分配数字并来回创建转换系统。这是一个糟糕的想法,如果实施得当,请放心看看,但我不建议您使用它。