【问题标题】:Introspection in ClojureClojure 中的自省
【发布时间】:2011-12-08 18:09:14
【问题描述】:
在 Clojure 中进行自省的最佳方式是什么?有没有类似 Python 的 dir 函数的东西?我对查找与我交互操作的 java 类上可用的方法特别感兴趣,但我也有兴趣找出 Clojure 中与自省相关的任何可用方法。
【问题讨论】:
标签:
clojure
introspection
【解决方案1】:
Michiel Borkent 和 Dave Ray 涵盖了互操作选项。
为了发现 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】:
如果你想发现方法,只需使用普通的 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得知类名本身已经是Class对象了!)
【解决方案5】:
要查找类实现的接口,请尝试supers
(supers clojure.lang.PersistentHashMap)