2011-09-05 9 views
11

Digamos que tengo una enumeración de Java. Por ejemplo:¿Cómo puedo parametrizar el acceso a una enumeración Java en clojure?

public enum Suits {CLUBS, DIAMONDS, HEARTS, SPADES}; 

Normalmente, yo puedo hacer algo en clojure con la enumeración de este modo:

(defn do-something [] 
    (let [s Suits/DIAMONDS] (...))) 

Pero, quiero escribir una función clojure que permite que la persona que llama para especificar qué instancia de enumeración de uso:

(defn do-something-parameterized [suit] 
    (let [s Suits/suit] (...))) 

la idea es permitir que una persona que llama pase en "DIAMONDS" y tienen la instancia DIAMONDS enumeración conseguir obligado a s en el let.

Podría tener una coincidencia cond con el parámetro, pero parece más complicado de lo necesario. Supongo que también podría usar una macro para construir Suits/ agregado a suit. ¿Es esta la manera de hacerlo o hay una forma no macro que me falta?

Respuesta

14

No hay necesidad de reflexión o mapas. Cada enum Java tiene un método estático valueOf que recupera un valor enum por nombre. Por lo tanto:

(defn do-something-parameterized [suit] 
    (let [s (Suit/valueOf (name suit))] ...)) 

Usando (name) permite cadenas o palabras clave a utilizar:

(do-something-parameterized "HEARTS") 
(do-something-parameterized :HEARTS) 
+0

de manera obvia, Dave. Estoy avergonzado de haberme olvidado de esto. – stand

+0

¡Ah, mucho mejor! –

1

me hizo una pregunta similar hace mucho tiempo, no con respecto a las enumeraciones, sino miembros de clase estáticos en general: How can I dynamically look up a static class member in Clojure?

La respuesta fue utilizar Java reflexión:

(defn do-something-parameterized [suit] 
    (let [s (.get (.getField Suits suit) nil)] (...))) 
0

Para mejorar el rendimiento, usted podría crear un mapa con la cadena que desea hacer coincidir, al tipo de enumeración, por ejemplo:

(def my-enum-map {"DIAMONDS" Suits/DIAMONDS, "SPADES" Suits/SPADES...}) 

Luego, en la función de hacer algo que se vería li ke:

(defn do-something-parameterized [suit] 
    (let [s (my-enum-map suit)] ...)) 

Y se puede construir este mapa durante el tiempo de carga utilizando la reflexión (en lugar de a mano), pero durante el tiempo de ejecución, es sólo un mapa de búsqueda.

0
(defmacro def-enum-alias 
    "Make name reference enum. 

    (def-enum-alias enum-name MyClass$MyEnum) 

    (enum-name Foo) 

    second desugars to MyClass$MyEnum/Foo" 
    [name enum] 
    `(defmacro ~name 
    ~(str "automatically generated alias for enum " 
      enum) 
    [member#] 
    (symbol-munge (quote ~enum) "/" member#))) 
Cuestiones relacionadas