Qual è il modo migliore per fare introspezione in Clojure? C'è qualcosa come la funzione di Python dir
? Sono particolarmente interessato a trovare i metodi disponibili sulle classi java con cui interagisco, ma sono anche interessato a scoprire tutto ciò che è disponibile in Clojure relativo all'introspezione.Introspection in Clojure
risposta
Se volete scoprire i metodi, basta usare pianura riflessione Java:
user=> (.getDeclaredMethods (.getClass {:a 1}))
#<Method[] [Ljava.lang.reflect.Method;@72b398da>
user=> (pprint *1)
[#<Method private int clojure.lang.PersistentArrayMap.indexOf(java.lang.Object)>,
#<Method public int clojure.lang.PersistentArrayMap.count()>,
#<Method public java.util.Iterator clojure.lang.PersistentArrayMap.iterator()>,
#<Method public boolean clojure.lang.PersistentArrayMap.containsKey(java.lang.Object)>,
#<Method public int clojure.lang.PersistentArrayMap.capacity()>,
#<Method public clojure.lang.IPersistentMap clojure.lang.PersistentArrayMap.empty()>,
...
è anche possibile scrivere un po 'più bello con una macro filettatura:
(-> {:a 1} .getClass .getDeclaredMethods pprint)
o
(-> clojure.lang.PersistentArrayMap .getDeclaredMethods pprint)
(Ho appena saputo da #clojure IRC che il nome della classe stessa è già l'oggetto Class!)
'' (anche .getDeclaredMethods (class {: a 1})) 'funziona anche. – Mars
Se si utilizza 1.3, c'è clojure.reflect che consente di ispezionare, manipolare, ecc. Informazioni sulle classi Java. Sono anche appassionato dello clojure.contrib.repl-utils/show dei vecchi contributi se questa è un'opzione per te.
Verificare clojure.contrib.repl-utils
e show
in particolare.
http://richhickey.github.com/clojure-contrib/repl-utils-api.html#clojure.contrib.repl-utils/show
Sono utility per voi per analizzare gli oggetti e le classi nel REPL, ma il codice è un buon esempio di come esplorare le classi programatically.
Michiel Borkent e Dave Ray hanno coperto le opzioni di interoperabilità.
Per scoprire le funzioni Clojure, ci sono un paio di opzioni nello spazio dei nomi clojure.repl
(che sono probabilmente già incluse nel REPL per impostazione predefinita).
dir
:
=> (require 'clojure.set)
nil
=> (dir clojure.set)
difference
index
intersection
join
map-invert
project
rename
rename-keys
select
subset?
superset?
union
apropos
:
=> (apropos #"^re-")
(re-pattern re-matches re-matcher re-groups re-find re-seq)
find-doc
:
=> (find-doC#"^re-")
-------------------------
clojure.core/re-find
([m] [re s])
Returns the next regex match, if any, of string to pattern, using
java.util.regex.Matcher.find(). Uses re-groups to return the
groups.
-------------------------
clojure.core/re-groups
([m])
Returns the groups from the most recent match/find. If there are no
nested groups, returns a string of the entire match. If there are
nested groups, returns a vector of the groups, the first element
being the entire match.
-------------------------
....
Per trovare interfacce implementate da una classe, provare supers
(supers clojure.lang.PersistentHashMap)
clojure.contrib.repl-utils
si è trasferito in clojure.reflect
.
È ora possibile chiamare come il seguente:
(->> (clojure.reflect/reflect java.lang.String)
:members
clojure.pprint/pprint)
Forse clojure.reflect merita di essere esaminata pure. http://clojure.github.io/clojure/clojure.reflect-api.html – claj