假设以下内容,
(in-ns silly.fun)
(def a 1)
(defn fx [b]
((fn [c] (return-all-symbols)) (first b)))
我想知道是否可以使用return-all-symbols函数来返回当前作用于其调用范围的符号/值的映射。因此,假设上面已经编译并且我们位于< silly.fun命名空间中,我们可以运行类似下面的内容。
(fx [:hello]) => {"a" 1, "b" [:hello], "c" :hello}
我想使用return-all-symbols进行调试。是否可以返回所有符号?如果是这样,它的实施是什么?
答案 0 :(得分:8)
这是可能的,但正如你所定义的那样,你会非常难过:你不想要一个包含数百个条目的地图,这些条目引用了clojure.core中的所有功能!即使您只查看当前名称空间,也忘记包含fx
,这是一个值为函数的符号。另外,宏通常会出现您不想要的词汇符号。例如,(let [[x y] foo])
将显示四个可用符号:foo,x,y和类似vec__auto__4863
的内容。
无论如何,你可能不得不忍受对这些问题的一些妥协,否则(而且我认为这更好)指定你真正想要一个地图的符号。但要自动获取(a)词法或(b)在当前命名空间中定义的符号的值,以及(c)不映射到函数,您可以使用:
(defmacro return-all-symbols []
(let [globals (remove (comp :macro meta val) (ns-publics *ns*))
syms (mapcat keys [globals, &env])
entries (for [sym syms]
[`(quote ~sym) sym])]
`(into {}
(for [[sym# value#] [~@entries]
:when (not (fn? value#))]
[sym# value#]))))
(def a 1)
(defn fx [b]
((fn [c] (return-all-symbols)) (first b)))
(fx [:hello])
;=> {a 1, c :hello, b [:hello]}
答案 1 :(得分:2)
命名空间包含一个包含所有当前范围的变量的地图,它可以为您提供所需的部分内容。它会错过来自(let [x 4] (return-all-symbols))
等表达式的lexicaly范围符号,但仍可能对调试有用:
core> (take 2 (ns-map *ns*))
([sorted-map #'clojure.core/sorted-map] [read-line #'clojure.core/read-line])
如果您需要更多,那么您可能需要一个使用java调试的真实调试器 接口。看看the clojure debugging toolkit
答案 2 :(得分:2)
(ns-interns)可能就是您想要的,但使用(ns-map)中包含的(lazy-seq)适用于大型命名空间。
1 (ns-map 'clojure.core)
2 {sorted-map #'clojure.core/sorted-map, read-line #'clojure.core/read-line, re-pattern #'clojure.core/re-pattern, keyword? #'clojure.core/keyword?, ClassVisitor clojure.asm.ClassVisitor, asm-type #'clojure.core/asm-type, val #'clojure.core/val, ...chop...}