如何Clojure中得到论证的名字吗?(How to get name of argument in

2019-09-21 00:18发布

我想获得一个函数以外定义的变种的名称,在一个函数中。 该名称应该是我在原来的定义,而不是任何嵌套绑定在那里我实际上是试图使用名称的范围中使用的名称。

所以我想这样做(学术为例):

(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<<

我能够基于一些东西,我发现这样做宏:

(defmacro get-var-name [x]
  `(:name (meta (var ~x))))

这个工作叫做例如,从REPL时,但编译器扼流圈从“内”范围如调用时

(defn another-func [y]
  (get-var-name y))

编译器说“的说法无法解析变种Y”。 (macroexpand...)表明它试图找出在当前名字空间的局部变量Y,而不是在目前的命名空间中的原始变量。 我认为(var... )查找命名空间只乏,所以这可以防止宏观无论从内部还是功能的其他结合,如工作let

我坚持有从那里我定义变量并一起传递,它作为一个额外的参数相同的范围内手动获取变量名。 有没有通过绑定点的链条传递变量名称信息,使用它的更优雅的方式? 这将是坏蛋。

谢谢

Answer 1:

这是不可能得到一个函数内外部范围使用变种的名称-函数只接收一个在运行时的参数,而不是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 <<

这是很丑陋 - 你当然不希望被写入所有宏代码,只是为了得到这个功能! 如果你建立某种基于宏观的DSL它可能是有意义的,虽然在一些专门的情况下,例如。



Answer 2:

您可以通过实际的VAR的功能,而不是使用var解析值#'读者宏观如下图所示:

user=> (defn f1 [x1] (println "hello, you passed var name >>" (:name (meta x1)) "<<"))
#'user/f1
user=> (defn f2 [x2] (f1 x2))
#'user/f2
user=> (defn f3 [x3] (let [zzz x3] (f2 zzz)))  
#'user/f3
user=> (def my-var 3.1414926)
#'user/my-var
user=> (f3 #'my-var)
hello, you passed var name >> my-var <<

如果你想绑定到VAR值,你可以使用var-get函数来进行。



Answer 3:

为什么不通过(get-var-name _symbol-here_)到功能,您将要使用的变数名称的体内? 例如,使用完全相同的相同的定义get-var-namef2f3 ,和my-var您已上面给出的(但改变f1略):

(defmacro get-var-name [x]
  `(:name (meta (var ~x))))
(defn f1 [x1] (println "hello, you passed var name >>" x1 "<<"))
(defn f2 [x2] (f1 x2))
(defn f3 [x3] (let [zzz x3] (f2 zzz)))
(def my-var 3.1414926)
=> (f3 (get-var-name my-var))
hello, you passed var name >> my-var <<
=> nil

也许有时候,你也会想引用的符号是指在函数体的值。 例如,我们在说f1要同时打印出由变数名称引用的值。 这里是你如何能做到这一点:

(defn f1 [x1] (println "hello, you passed var name >>" x1 "<<"
                       "\nwhich refers to value >>" @(resolve x1) "<<"))
=> (f3 (get-var-name my-var))
hello, you passed var name >> my-var << 
which refers to value >> 3.1414926 <<
=> nil

注意@(resolve x1) -这是恢复该值的东西my-var是指(反过来my-var是指价值x1 )。

另外,我想提一提,你目前执行的get-var-name时传递的参数是不是没有一个符号,或者是一个符号,但当前未绑定到一个值都将抛出异常。 这是你想要的行为?

如果我的建议并没有回答你的问题,那么就好像你不想必须通过(get-var-name _symbol-here_)到最终可能使用var名称的功能,而是出于某种原因真的希望能够做的(get-var-name ...)从函数体内。 如果是这样的话,为什么它要能够做到这样? 或者,如果你觉得我还没有回答你的问题的一些其他的原因,那是什么原因呢?



文章来源: How to get name of argument in Clojure?