Интроспекция в 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, что имя самого класса уже является объектом класса!)

Ответ 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/...