Интроспекция в Clojure
Каков наилучший способ сделать интроспекцию в Clojure? Есть что-то вроде функции Python dir
? Мне особенно интересно найти методы, доступные для классов Java, с которыми я взаимодействую, но я также заинтересован в том, чтобы узнать все, что доступно в Clojure, связанных с интроспекцией.
Ответы
Ответ 1
Мичиэль Боркент и Дейв Рэй имеют варианты взаимодействия.
Для обнаружения функций Clojure существует пара опций в пространстве имен clojure.repl
(которые, вероятно, уже упоминаются в вашем REPL по умолчанию).
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.
-------------------------
....
Ответ 2
Если вы используете 1.3, clojure.reflect, который позволяет вам проверять, обрабатывать и т.д. информацию о Java-классах. Я также люблю clojure.contrib.repl-utils/show от старого вкладчика, если это вариант для вас.
Ответ 3
Если вы хотите найти методы, просто используйте простое отражение 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()>,
...
Вы также можете записать это немного лучше с помощью макроса:
(-> {:a 1} .getClass .getDeclaredMethods pprint)
или
(-> clojure.lang.PersistentArrayMap .getDeclaredMethods pprint)
(Я только что узнал из # clojure IRC, что имя самого класса уже является объектом класса!)
Ответ 4
Проверьте clojure.contrib.repl-utils
и show
в частности.
http://richhickey.github.com/clojure-contrib/repl-utils-api.html#clojure.contrib.repl-utils/show
Это утилиты для интроспекции объектов и классов в REPL, но код является хорошим примером того, как программно изучить классы.
Ответ 5
Чтобы найти интерфейсы, реализованные классом, попробуйте supers
(supers clojure.lang.PersistentHashMap)
Ответ 6
clojure.contrib.repl-utils
переместился на clojure.reflect
.
Теперь вы можете назвать его следующим:
(->> (clojure.reflect/reflect java.lang.String)
:members
clojure.pprint/pprint)
fooobar.com/info/345506/...