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

Ste*_*gle 6 debugging symbols clojure

假设如下,

(in-ns silly.fun)

(def a 1)

(defn fx [b]
  ((fn [c] (return-all-symbols)) (first b)))
Run Code Online (Sandbox Code Playgroud)

我想知道是否有可能返回所有符号函数,它将返回当前作用于其调用的符号/值的映射.因此,假设上面已经编译并且我们在'silly.fun命名空间中,我们可以运行类似下面的内容.

(fx [:hello]) => {"a" 1, "b" [:hello], "c" :hello}
Run Code Online (Sandbox Code Playgroud)

我想使用return-all-symbols进行调试.是否可以返回所有符号?如果是这样,它的实施是什么?

ama*_*loy 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]}
Run Code Online (Sandbox Code Playgroud)