Перечисления и 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
, который присваивал номера символам и создавал системы преобразования взад и вперед. Это ужасная идея реализована достаточно хорошо, так что не стесняйтесь посмотреть, но я не рекомендую вам ее использовать.