Перечисления и Clojure

В мире Java/C люди часто используют перечисления. Если я использую библиотеку Java, которая использует перечисления, я могу конвертировать между ними и ключевыми словами, например, используя (. java.lang.Enum valueOf e..., (aget ^"[Ljava.lang.Enum;" (. e (getEnumConstants)) i) и некоторое отражение. Но в мире Clojure, нужны ли люди когда-либо как enum (именованное целое число)? Если нет, то как их код структурирован, что они им не нужны? Если да, то какой эквивалент? Я чувствую, что я действительно спрашиваю об индексах (для циклов), которые редко используются в функциональном программировании (я использовал индексирование по карте только один раз до сих пор).

Ответы

Ответ 1

Для почти всего кода Clojure я видел, что ключевые слова , как правило, используются вместо Enums, они разнесены по именам и имеют все другие полезные свойства ключевых слов, а их гораздо легче писать. Они не являются точными, потому что они более динамичны (как при динамическом наборе текста), чем Java enums

как для индексирования и петли, я нахожу более идиоматичным отображение по последовательности ключевых слов:

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

чем перебирать значения в перечислении, которые мне еще предстоит найти в коде Clojure, хотя пример, скорее всего, существует; -)

Ответ 2

Как Артур указывает - ключевые слова обычно используются в Clojure вместо перечислений.

Вы не увидите многократно использованных индексов - они не особенно идиоматичны в Clojure (или большинстве других языков программирования)

Некоторые другие варианты, о которых стоит знать:

  • Использовать Java перечисления напрямую - например. java.util.concurrent.TimeUnit/SECONDS
  • Определите свои собственные константы с помощью vars, если вы хотите числовые значения - например. (def ^:const PURPLE 1)
  • Вы даже можете реализовать макрос defenum, если вам нужны более сложные функции перечисления с простым синтаксисом.

Ответ 3

Да, используйте ключевые слова в большинстве мест, где Java-программисты будут использовать перечисления. В редком случае вам нужно число для каждого из них, вы можете просто определить карту для преобразования: {:dog 0, :rabbit 1, ...}.

С другой стороны, одна из первых библиотек Clojure, которые я написал, была именно такой: макрос defenum, который присваивал номера символам и создавал системы преобразования взад и вперед. Это ужасная идея реализована достаточно хорошо, так что не стесняйтесь посмотреть, но я не рекомендую вам ее использовать.