Function 如何从clojure中的符号中获取函数名?

Function 如何从clojure中的符号中获取函数名?,function,clojure,symbols,name-lookup,Function,Clojure,Symbols,Name Lookup,假设我将x定义为符号函数foo (defn foo [x] x) (def x foo) 如果只给定x,是否可以发现名称“foo” 在foo中是否有方法查找函数x的名称?在本例中为“foo” (foo x) 是否存在或可能创建以下功能: (get-fn-name x) foo 不清楚您为什么要这样做-当您这样做(def x foo)时,实际上是将名称x赋予命名空间中的新变量。它恰好与foo具有相同的值(即,它包含相同的函数),但在其他方面完全独立于foo。使用Java类比,这就像对同一个

假设我将x定义为符号函数foo

(defn foo [x] x)

(def x foo)
如果只给定x,是否可以发现名称“foo”

在foo中是否有方法查找函数x的名称?在本例中为“foo”

(foo x)
是否存在或可能创建以下功能:

(get-fn-name x)
foo

不清楚您为什么要这样做-当您这样做
(def x foo)
时,实际上是将名称
x
赋予命名空间中的新变量。它恰好与
foo
具有相同的值(即,它包含相同的函数),但在其他方面完全独立于foo。使用Java类比,这就像对同一个对象有两个引用一样

为什么要继续获取名称
foo

如果确实希望执行类似的操作,可以在包含原始符号的函数上使用一些自定义元数据:

(def foo 
  (with-meta
    (fn [x] x)
    {:original-function `foo}))

(def bar foo)

(defn original-function [v]
  "Returns the :original-function symbol from the metadata map"
  (:original-function (meta v)))

(original-function bar)
=> user/foo

最近在这个网站上也提出了类似的问题;看

当您执行
(def x foo)
时,您将x定义为“位于
foo
的值”,而不是“
foo
本身”。一旦
foo
解析为其值,该值就不再与
foo
有任何关系

因此,也许您现在看到了问题的一个可能答案:当您开始定义
x
时,不要解析
foo
。而不是做

(def x foo)
…做

(def x 'foo)
现在,如果您尝试获取
x
的值,您将获得
foo
(字面意思),而不是
foo
解析为的值

user> x
=> foo
但是,这可能有问题,因为有时您可能还希望能够使用
x
获得
foo
解析为的值。但是,您可以通过执行以下操作来做到这一点:

user> @(resolve x)
=> #<user$foo user$foo@157b46f>
现在,看看这个:

user> (str foo)
=> "user$foo@1e2afb2"
user> (str x)
=> "user$foo@1e2afb2"
酷。这仅仅是因为
foo
解析为一个函数,该函数恰巧有一个类似var的名称,该名称与
x
相同,因为它引用了相同的函数。请注意,“foo”包含在
(strx)
(以及
(foo x)
)生成的字符串中。这是因为函数的var名称显然是通过向后引用最初用于定义它的符号创建的。我们将利用这个事实,从任何函数中找到这个符号


所以,我写了一篇文章来查找函数var名称字符串中的“foo”。它不是查找“foo”,而是查找任何子字符串——用正则表达式术语,
“*”
——前面有一个
\$
字符——用正则表达式术语,
”(?谢谢,这对我有用。我需要函数能够报告它自己的名称(也许它可以更直接地这样做?)以及它作为参数接收的其他函数的名称。很高兴它能为您工作。尽管我会仔细考虑您正在做什么-使函数“能够报告自己的名称”"听起来你试图强迫函数做一些它们不是为之设计的事情。如果你试图让函数以类似对象的方式运行,也许你应该改用defrecord?这是一个令人惊讶的答案,方法一正是我所需要的。如果你已经写了一本关于Clojure的书,或者正在计划一本,请告诉我。我会的买吧。
user> (str foo)
=> "user$foo@1e2afb2"
user> (str x)
=> "user$foo@1e2afb2"
user> (re-find #"(?<=\$).*(?=@)"
               (str x))
=> "foo"
user> (symbol (re-find #"(?<=\$).*(?=@)"
                       (str x)))
=> foo
(defn get-fn-init-sym [f]
  (symbol (re-find #"(?<=\$).*(?=@)" (str f))))
(defn get-fn-init-sym [f]
  (->> (str f)
       (re-find #"(?<=\$).*(?=@)")
       symbol))
user> (get-fn-init-sym x)
=> foo
user> (->> (dissoc (ns-map *ns*) 'x)
           (filter #(identical? (let [v (val %)]
                                  (if (var? v) @v v))
                                x))
           first
           key)
=> foo
(defn find-equiv-sym [sym]
  (->> (dissoc (ns-map *ns*) sym)
       (filter #(identical? (let [v (val %)]
                              (if (var? v) @v v))
                            @(resolve sym)))
       first
       key))
user> (find-equiv-sym 'x)
=> foo