2011-01-10 7 views

Respuesta

5

que terminó con la siguiente implementación:

(defn protocol? [maybe-p] 
    (boolean (:on-interface maybe-p))) 

(defn all-protocols [] 
    (filter #(protocol? @(val %)) (ns-publics *ns*))) 

(defn implemented-protocols [sym] 
    (filter #(satisfies? @(val %) sym) (all-protocols))) 

En primer lugar, busca todos los símbolos en el espacio de nombres actual (por supuesto puede extender esto a todos los espacios de nombres) si son definiciones de protocolos o neta (todos -protocolos). Luego busca un símbolo dado si satisface uno de estos protocolos.

¿El protocolo? función utiliza la tecla: en la interfaz que no está documentada afaik, por lo que esta función no es portátil.

+0

'protocolo?' Falla en un mapa ordenado, al menos en Clojure 1.8. Ver [esta pregunta] (http://stackoverflow.com/q/37410580/1393162). –

0

No puedo probar esto en este momento, pero es posible que desee probar el método de la clase Java: getGenericInterfaces. Esto debería darle una lista de interfaces. Probablemente haya otras maneras de obtener esta información usando métodos similares pero no he buscado.

Si también observa el código fuente, verá cómo se configuran los protocolos (puede acceder a la fuente haciendo clic en los enlaces en la api de clojure). En Clojure 1.3 existe una función de 'privado' que tiene este aspecto:

(defn- protocol? 
    [maybe-p] 
    (boolean (:on-interface maybe-p))) 

Esta función es utilizada por la función de Clojure extend para comprobar que realmente ha proporcionado un protocolo. Si realiza su propia función de esa manera, puede filtrar los resultados de getGenericInterfaces. Como se trata de un detalle interno, puede estar sujeto a cambios.

+0

getGenericInterfaces me da (clojure.lang.IObj clojure.lang.ILookup clojure.lang.IKeywordLookup clojure.lang.IPersistentMap java.util.Map java.io.Serializable) pero no el protocolo implementado. Creo que tendré que profundizar en el código fuente para ver cómo se hace. –

+0

Acabo de volver a mi máquina, y no estoy llegando más allá de usted. Probablemente sea más sencillo usar 'getInterfaces' como una alternativa razonable a' getGenericInterfaces'. Me pregunto qué pasará si AOT compila la cosa. – hutch

+2

Parte del punto de los protocolos es que una clase no necesita implementar una interfaz para extender un protocolo: puede definir su propio protocolo y luego decir que alguna clase preexistente lo extiende con '(extender ExistingClass MyProtocol ...)'. Por lo tanto, es natural tener una manera de preguntar "qué clases amplían este protocolo", pero no una manera de formular la pregunta inversa. –

Cuestiones relacionadas