1 Introduction
1.1 Overview
std.lib.enum is part of the standard foundation library set. This page collects the public API reference for the namespace.
2 Walkthrough
2.1 Inspecting Java enums
std.lib.enum makes it easy to work with Java enums from Clojure. Check if a class is an enum, list its values, and convert between strings, keywords, and enum instances.
check and list enum values
^{:refer std.lib.enum/enum? :added "3.0"}
(enum? java.lang.annotation.ElementType)
=> true
^{:refer std.lib.enum/enum-values :added "3.0"}
(->> (enum-values ElementType)
(map str)
(set))
=> (contains #{"TYPE" "FIELD" "METHOD" "PARAMETER" "CONSTRUCTOR"})
convert to and from enum instances
^{:refer std.lib.enum/create-enum :added "3.0"}
(create-enum "TYPE" ElementType)
=> ElementType/TYPE
^{:refer std.lib.enum/to-enum :added "3.0"}
(to-enum :field ElementType)
=> ElementType/FIELD
^{:refer std.lib.enum/enum-map :added "3.0"}
(enum-map ElementType)
=> (satisfies [:annotation-type
:constructor
:field
:local-variable
:method
:module
:package
:parameter
:record-component
:type
:type-parameter
:type-use]
(comp vec sort keys))
3 API
v 3.0
(defn create-enum
([s type]
(loop [[e :as values] (enum-values type)]
(cond (empty? values)
(throw (ex-info "Cannot create enum" {:type type
:value s}))
(= (str e) s) e
:else
(recur (rest values))))))
link
(create-enum "TYPE" ElementType) => ElementType/TYPE
v 3.0
(definvoke enum-map
[:memoize]
([type]
(coll/map-juxt [(comp keyword case/spear-case coerce/to-string)
identity]
(enum-values type))))
link
(enum-map ElementType) => (satisfies [:annotation-type :constructor :field :local-variable :method :module :package :parameter :record-component :type :type-parameter :type-use] (comp vec sort keys))
v 3.0
(defn enum-map-form
([^Class type]
(coll/map-juxt [(comp keyword case/spear-case str)
#(symbol (.getName type) (str %))]
(enum-values type))))
link
(enum-map-form ElementType) => '{:package java.lang.annotation.ElementType/PACKAGE, :type-use java.lang.annotation.ElementType/TYPE_USE, :method java.lang.annotation.ElementType/METHOD, :field java.lang.annotation.ElementType/FIELD, :type java.lang.annotation.ElementType/TYPE, :module java.lang.annotation.ElementType/MODULE, :record-component java.lang.annotation.ElementType/RECORD_COMPONENT :type-parameter java.lang.annotation.ElementType/TYPE_PARAMETER, :constructor java.lang.annotation.ElementType/CONSTRUCTOR, :local-variable java.lang.annotation.ElementType/LOCAL_VARIABLE, :annotation-type java.lang.annotation.ElementType/ANNOTATION_TYPE, :parameter java.lang.annotation.ElementType/PARAMETER}
v 3.0
(defmacro enum-map>
([type]
(enum-map-form (resolve type))))
link
(enum-map> ElementType) => {:package ElementType/PACKAGE, :type-use ElementType/TYPE_USE, :method ElementType/METHOD, :field ElementType/FIELD, :type ElementType/TYPE, :module ElementType/MODULE, :record-component ElementType/RECORD_COMPONENT :type-parameter ElementType/TYPE_PARAMETER, :constructor ElementType/CONSTRUCTOR, :local-variable ElementType/LOCAL_VARIABLE, :annotation-type ElementType/ANNOTATION_TYPE, :parameter ElementType/PARAMETER}
v 3.0
(defn enum-values
([^Class type]
(let [method (.getMethod type "values" (make-array Class 0))
values (.invoke method nil (object-array []))]
(seq values))))
link
(->> (enum-values ElementType) (map str)) => (contains ["TYPE" "FIELD" "METHOD" "PARAMETER" "CONSTRUCTOR"] :in-any-order :gaps-ok)
v 3.0
(defn enum?
([type]
(if (-> (cls/ancestor:list type)
(set)
(get java.lang.Enum))
true false)))
link
(enum? java.lang.annotation.ElementType) => true (enum? String) => false
v 3.0
(defn to-enum
([s type]
(let [key ((comp keyword case/spear-case coerce/to-string) s)]
(or (get (enum-map type) key)
(throw (ex-info "Cannot find the enum value."
{:input s
:key key
:type type
:options (sort (keys (enum-map type)))}))))))
link
(to-enum "TYPE" ElementType) => ElementType/TYPE (to-enum :field ElementType) => ElementType/FIELD
4 std.lib.enum: A Comprehensive Summary
The std.lib.enum namespace provides a set of utility functions for working with Java enum types in Clojure. It simplifies common tasks such as checking if a class is an enum, retrieving its values, converting between string/keyword representations and enum instances, and generating maps of enum values. This module is particularly useful for enhancing interoperability with Java APIs that extensively use enums.
Key Features and Concepts:
- Enum Type Checking:n
enum? [type]: A predicate that returnstrueif the giventype(ajava.lang.Class) is a Java enum, andfalseotherwise. It checks if the type's ancestor list includesjava.lang.Enum.nn2. Enum Value Retrieval:nenum-values [type]: Returns a sequence of all enum instances for a given enumtype. It achieves this by reflectively invoking the staticvalues()method available on all Java enum classes.nn3. Enum Instance Creation:ncreate-enum [s type]: Creates an enum instance of the specifiedtypefrom its string representations. It iterates through the enum's values to find a match, throwing an exception if no match is found.nn4. Enum Mapping and Conversion:nenum-map [type]: A memoized function that returns a map where keys are kebab-cased keywords (derived from the enum's string name) and values are the corresponding enum instances. This provides a convenient way to look up enum values using Clojure keywords.nenum-map-form [type]: A helper function that generates the Clojure form forenum-map, useful for macro expansion.nenum-map> [type]: A macro that expands to the result ofenum-map-form, allowing enum maps to be generated at compile time.n *to-enum [s type]: Converts a string or keywordsinto an enum instance of the specifiedtype. It usesenum-mapfor efficient lookup, handling both string and keyword inputs by converting them to kebab-cased keywords.
Usage and Importance:
The std.lib.enum module is crucial for applications within the foundation-base project that need to interact with Java APIs that utilize enums. It provides:
- Simplified Interoperability: Bridges the gap between Clojure's dynamic nature and Java's static enum types, making it easier to work with Java enums in a Clojure-idiomatic way.n Type Safety and Validation: Functions like
create-enumandto-enumensure that attempts to create enum instances from invalid strings or keywords are caught, preventing runtime errors.n Readability and Convenience: Theenum-mapandenum-map>functions provide a convenient keyword-based lookup mechanism, improving code readability and reducing boilerplate when dealing with enum values.n* Performance: The use of memoization inenum-mapensures that the mapping of enum values is computed only once, improving performance for repeated lookups.
By offering these specialized utilities for Java enums, std.lib.enum enhances the foundation-base project's ability to seamlessly integrate with and leverage the broader Java ecosystem.