-->

Enums and Clojure

2020-08-09 11:42发布

问题:

In the Java/C world, people often use enums. If I'm using a Java library which using enums, I can convert between them and keywords, for example, using (. java.lang.Enum valueOf e..., (aget ^"[Ljava.lang.Enum;" (. e (getEnumConstants)) i), and some reflection. But in the Clojure world, do people ever need anything like an enum (a named integer) ? If not, how is their code structured that they don't need them ? If yes, what's the equivalent ? I sense I'm really asking about indices (for looping), which are rarely used in functional programming (I've used map-indexed only once so far).

回答1:

For almost all the Clojure code I have seen keywords tend to be used instead of Enums they are name-spaced and have all the other useful properties of keywords while being much easier to write. They are not an exact standin because they are more dynamic (as in dynamic typing) than Java enums

as for indexing and looping I find it more idiomatic to map over a sequence of keywords:

(map do-stuff [:a :b :c :d] (range)) 

than to loop over the values in an enumeration, which I have yet to find an example of in Clojure code, though an example very likely exists ;-)



回答2:

As Arthur points out - keywords are typically used in Clojure in place of enums.

You won't see numbered indexes used much - they aren't particularly idiomatic in Clojure (or most other functional programming languages)

Some other options worth being aware of:

  • Use Java enums directly - e.g. java.util.concurrent.TimeUnit/SECONDS
  • Define your own constants with vars if you want numeric values - e.g. (def ^:const PURPLE 1)
  • You could even implement a macro defenum if you wanted more advanced enum features with a simple syntax.


回答3:

Yes, use keywords in most places where Java programmers would use enums. In the rare case that you need a number for each of them, you can simply define a map for converting: {:dog 0, :rabbit 1, ...}.

On the other hand, one of the first Clojure libraries I wrote was just this: a defenum macro that assigned numbers to symbols and created conversion systems back and forth. It's a terrible idea implemented reasonably well, so feel free to have a look but I don't recommend you use it.



标签: clojure enums