15

What is the best way to do introspection in Clojure? Is there something like Python's dir function? I'm particularly interested in finding the methods that are available on java classes that I'm interoperating with, but I'm also interested in finding out anything that's available in Clojure related to introspection.

Frank Henard
  • 3,638
  • 3
  • 28
  • 41
  • 1
    Maybe clojure.reflect is worth looking into as well. http://clojure.github.io/clojure/clojure.reflect-api.html – claj Jan 23 '14 at 16:38

6 Answers6

15

Michiel Borkent and Dave Ray has the interop options covered.

For discovering Clojure functions, there are a couple of options in the clojure.repl namespace (which are likely already referred into your REPL by default).

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.
-------------------------
....
cemerick
  • 5,916
  • 5
  • 30
  • 51
11

If you want to discover methods, just use plain Java reflection:

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()>,
 ...

You can also write it a little nicer with a threading macro:

(-> {:a 1} .getClass .getDeclaredMethods pprint)

or

(-> clojure.lang.PersistentArrayMap .getDeclaredMethods pprint)

(I just learned from #clojure IRC that the name of the class itself is already the Class object!)

Michiel Borkent
  • 34,228
  • 15
  • 86
  • 149
11

If you're using 1.3, there's clojure.reflect which allows you to inspect, manipulate, etc. info about Java classes. I'm also fond of the clojure.contrib.repl-utils/show from old contrib if that's an option for you.

Dave Ray
  • 39,616
  • 7
  • 83
  • 82
3

To find interfaces implemented by a class, try supers

(supers clojure.lang.PersistentHashMap)

Malcolm Sparks
  • 369
  • 3
  • 4
3

clojure.contrib.repl-utils has moved to clojure.reflect.

You can now call it as the following:

(->> (clojure.reflect/reflect java.lang.String) 
     :members 
     clojure.pprint/pprint)

https://stackoverflow.com/a/17974908/262425

Community
  • 1
  • 1
ruseel
  • 1,578
  • 2
  • 21
  • 41
3

Check out clojure.contrib.repl-utils, and show in particular.

http://richhickey.github.com/clojure-contrib/repl-utils-api.html#clojure.contrib.repl-utils/show

These are utilities for you to introspect objects and classes in the REPL, but the code is a good example of how to explore classes programatically.

John Cromartie
  • 4,184
  • 27
  • 32