如何在Clojure中获得参数名称?

Son*_*oth 3 macros var clojure

我想从函数中获取函数外部定义的var的名称.该名称应该是我在原始定义范围内使用的名称,而不是我实际上尝试使用该名称的任何嵌套绑定.

所以我想做一些像(学术范例)的事情:

(defn f1 [x1] (println "hello, you passed var name >>" (get-var-name x1) "<<")
(defn f2 [x2] (f1 x2))
(defn f3 [x3] (let [zzz x3] (f2 zzz))
(def my-var 3.1414926)
(f3 my-var)
user> hello, you passed var name >>my-var<<
Run Code Online (Sandbox Code Playgroud)

我能够根据我发现的一些东西做这个宏:

(defmacro get-var-name [x]
  `(:name (meta (var ~x))))
Run Code Online (Sandbox Code Playgroud)

这在例如从REPL调用时起作用,但是当从"内部"范围调用时编译器会阻塞,例如

(defn another-func [y]
  (get-var-name y))
Run Code Online (Sandbox Code Playgroud)

编译器说"说无法解决var y". (macroexpand...)显示它试图在当前命名空间中找到局部变量y,而不是当前命名空间中的原始变量.我认为(var...)只查找命名空间变量,因此这可以防止宏在函数或其他绑定中工作let.

我不得不从我定义变量的相同范围手动获取变量名称并将其作为额外参数传递.有没有更优雅的方法通过一系列绑定将var名称信息传递到它所使用的点?那将是坏事.

谢谢

mik*_*era 8

无法获取函数中外部作用域中使用的var的名称- 该函数仅接收在运行时作为参数传递的,而不是var本身.

您唯一可能做的就是在每个级别使用宏而不是函数.这允许您在编译时通过不同的宏传递var本身:

(defmacro f1 [x1] `(println "hello, you passed var name >>" ~(str x1) "<<"))
(defmacro f2 [x2] `(f1 ~x2))
(defmacro f3 [x3] (let [zzz x3] `(f2 ~zzz)))

(f3 my-var)
=> hello, you passed var name >> my-var <<
Run Code Online (Sandbox Code Playgroud)

这非常难看 - 您当然不希望用宏来编写所有代码来获得此功能!它可能在某些特殊情况下有意义,例如,如果您正在创建某种基于宏的DSL.

  • 这,这一百倍.其他答案(到目前为止)同意提问者的假设,即vars参与并实际工作,但事实并非如此(正如问题中的最后一个例子所示). (4认同)