返回Clojure中所有当前作用域符号的表达式?

时间:2012-09-19 21:09:52

标签: debugging clojure symbols

假设以下内容,

(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进行调试。是否可以返回所有符号?如果是这样,它的实施是什么?

3 个答案:

答案 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...}